9

In my C# project have APIKeys.cs file which have const strings with API keys. I want those strings to be empty in Git server but have actual API keys in my local computer. So peoples who pull project can compile it without problem and still my local computer gonna have API keys in same file.

If I try to upload APIKeys.cs file with empty strings then I can't have local file with API keys because when I try to push it, it will overwrite empty APIKeys.cs file. Also I can't ignore this file too because it will remove empty APIKeys.cs file from Git server.

So what is best automated approach for this problem which will allow class file with empty strings in server, so project will be compileable when people pull it and have real class file in local computer?

1
  • Unfortunately there is no automatic way to do this (that I know of). You might have to just remove the file from the staging area every time you commit. Commented Feb 14, 2014 at 9:03

4 Answers 4

20

I figured another solution now which is not perfect but still good enough for me, example:

APIKeys.cs file:

public static partial class APIKeys
{
    public static readonly string ImgurClientID = "";
    public static readonly string ImgurClientSecret = "";
    public static readonly string GoogleClientID = "";
    public static readonly string GoogleClientSecret = "";
    public static readonly string PastebinKey = "";
    ...
}

APIKeysLocal.cs file:

public static partial class APIKeys
{
    static APIKeys()
    {
        ImgurClientID = "1234567890";
        ImgurClientSecret = "1234567890";
        GoogleClientID = "1234567890";
        GoogleClientSecret = "1234567890";
        PastebinKey = "1234567890";
        ...
     }
}

Ignore APIKeysLocal.cs file in Git and people who don't have this file can still be able to compile project if they remove this file from solution explorer.

I also automatically create empty APIKeysLocal.cs file if it is not already exists using project pre build event:

cd $(ProjectDir)APIKeys\

if not exist APIKeysLocal.cs (
    type nul > APIKeysLocal.cs
)

That way user don't need to do anything to be able to compile project.

Sign up to request clarification or add additional context in comments.

2 Comments

I like this solution. One thing: Why would did you create an empty APIKeysLocal.cs file when it isn't needed to compile? I don't know much about pre-build events but if instead, it built a local file based off of a template that also had empty strings in the constructor for others to fill, then that would make more sense. Then others can see how your local file is setup and do the same.
Protip for public repos, keep a copy of this file with empty fields in a different name if the repo is going to be public.
12

Accept that you cannot hide unencrypted private keys in a public space.

What you can do is move the keys to a private space, and then reference that private space from code.

Your private space might be environment variables or the Windows registry, it should be something outside the source code of your app.

Another approach is to create a new config file (e.g. keys.config) specifically for storing private keys, and then exclude this file from source control.

This means you don't share your private keys, but it also means that you need to document (perhaps in readme.md) that users will need to recreate their own keys.config. Even better (thanks @Joey) is to include a sample config file (keys.sample.config) in the solution, illustrating what's needed.

Here is an example

4 Comments

I usually use the config file approach and include a foo.config.sample in source control which then can be copied to foo.config where the actual keys or passwords or developer-specific settings reside and which is also ignored by source control.
An empty keys.config is a bad idea because changes will invariable find their way into source control again :-). The actual config should not ever be checked in.
I know i can't hide keys but API service owners have rule to not share keys in public so even if it is very easy to decompile and see them in C# application still i must hide them in Git. I don't think storing 30 different uploader api keys in registry is good idea.
I checked config file now and when project is compiled it creates config file where executable is located so API keys will be easily visible in that config file when peoples use installer and this is not allowed by some API service owners.
4

You've got two options:

  1. Tell Git to ignore changes to APIKeys.cs on your local machine:

    git update-index --skip-worktree APIKeys.cs
    

    This will cause local changes not to get committed. If you ever do want to commit changes to the file, you'll have to undo this with the --no-skip-worktree flag.

  2. Rename the APIKeys.cs file to something like APIKeys.template.cs, containing the blank strings that you want to share. Keep this file in your repository. Copy that file to APIKeys.cs. Add APIKeys.cs to your .gitignore. Add instructions to copy the template file and modify with local settings.

    git mv APIKeys.cs APIKeys.template.cs
    $EDITOR APIKeys.template.cs
    git commit
    cat APIKeys.cs >> .gitignore
    cp APIKeys.template.cs APIKeys.cs
    

2 Comments

I tried assume-unchanged and it is working perfectly. When i do pull, Git not overwrite my api keys file with empty one and i can't push my api keys to server to overwrite empty file so it is exactly what i want. But if one developer forget to do assume-unchanged then that person can accidentally push api keys which is problem. But i don't think i can find better solution than assume-unchanged.
@Jaex, yes, that is a real risk with --assume-unchanged. The other method I suggested, which is echoed by Ed Guiness and Joey, is actually my preferred approach.
1

Isn't this very similar to the problem of injecting a build number into your component? The way I do that is to have a pre-build step that generates a file called AssemblyVersionInfo.cs based on some environment variable. You could do the same thing with your API Keys.

In the pre-build step for the component that compiles in the API keys put something like this:-

if not defined API_KEY set API_KEY=DEFAULT_KEY
echo public class ApiKeys>"$(SolutionDir)src\ApiKeys.cs"
echo {>>"$(SolutionDir)src\ApiKeys.cs"
echo public const string Key="%API_KEY%";>>"$(SolutionDir)src\ApiKeys.cs"
echo }>>"$(SolutionDir)src\ApiKeys.cs"

Then you set either a user or system environment variable on your local machine with the real key in it.

setx API_KEY THE_REAL_KEY

To avoid Git wanting to commit the file just add it to the .gitignore.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.