Files
jims-blog/blogs/hiding-api-keys-from-git/index.html
2023-01-21 22:30:31 +00:00

25 lines
14 KiB
HTML

<!doctype html><html><head><meta charset=utf-8><meta name=viewport content="width=device-width,initial-scale=1"><meta http-equiv=x-ua-compatible content="ie=edge"><link rel=icon href=/fav.png type=image/png><link rel=preconnect href=https://fonts.googleapis.com><link rel=preconnect href=https://fonts.gstatic.com crossorigin><link rel=preload as=style href="https://fonts.googleapis.com/css2?family=Alata&family=Lora&family=Muli:ital,wght@0,400;0,500;0,600;0,700;1,400;1,500;1,600;1,700&family=Roboto&family=Muli:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap"><link rel=stylesheet href="https://fonts.googleapis.com/css2?family=Alata&family=Lora&family=Muli:ital,wght@0,400;0,500;0,600;0,700;1,400;1,500;1,600;1,700&family=Roboto&family=Muli:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap" media=print onload='this.media="all"'><noscript><link href="https://fonts.googleapis.com/css2?family=Alata&family=Lora&family=Muli:ital,wght@0,400;0,500;0,600;0,700;1,400;1,500;1,600;1,700&family=Roboto&family=Muli:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap" rel=stylesheet></noscript><link rel=stylesheet href=/css/font.css media=all><meta property="og:title" content="Hiding API keys from Git"><meta property="og:description" content="I&rsquo;ve been working on a Xamarin app using Azure Cognitive Services to do image recognition, and one of the stumbling blocks I&rsquo;ve faced is what to do with my API keys. I want to make the app open source as an example of how to use these services, but don&rsquo;t want to check my API keys into Git to be available to all - after all, bad things can happen."><meta property="og:type" content="article"><meta property="og:url" content="https://jimbobbennett.dev/blogs/hiding-api-keys-from-git/"><meta property="og:image" content="https://jimbobbennett.dev/blogs/hiding-api-keys-from-git/banner.png"><meta property="article:section" content="blogs"><meta property="article:published_time" content="2017-12-28T19:35:50+00:00"><meta property="article:modified_time" content="2017-12-28T19:35:50+00:00"><meta property="og:site_name" content="JimBobBennett"><meta name=twitter:card content="summary_large_image"><meta name=twitter:image content="https://jimbobbennett.dev/blogs/hiding-api-keys-from-git/banner.png"><meta name=twitter:title content="Hiding API keys from Git"><meta name=twitter:description content="I&rsquo;ve been working on a Xamarin app using Azure Cognitive Services to do image recognition, and one of the stumbling blocks I&rsquo;ve faced is what to do with my API keys. I want to make the app open source as an example of how to use these services, but don&rsquo;t want to check my API keys into Git to be available to all - after all, bad things can happen."><meta name=twitter:site content="@jimbobbennett"><meta name=twitter:creator content="@jimbobbennett"><link rel=stylesheet href=https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/css/bootstrap.min.css integrity=sha384-1BmE4kWBq78iYhFldvKuhfTAU6auU8tT94WrHftjDbrCEXSU1oBoqyl2QvZ6jIW3 crossorigin=anonymous><link rel=stylesheet href=/css/header.css media=all><link rel=stylesheet href=/css/footer.css media=all><link rel=stylesheet href=/css/theme.css media=all><link rel="shortcut icon" type=image/png href=/fav.png><link rel="shortcut icon" sizes=192x192 href=/fav.png><link rel=apple-touch-icon href=/fav.png><link rel=alternate type=application/rss+xml href=https://jimbobbennett.dev/index.xml title=JimBobBennett><script type=text/javascript>(function(e,t,n,s,o,i,a){e[n]=e[n]||function(){(e[n].q=e[n].q||[]).push(arguments)},i=t.createElement(s),i.async=1,i.src="https://www.clarity.ms/tag/"+o,a=t.getElementsByTagName(s)[0],a.parentNode.insertBefore(i,a)})(window,document,"clarity","script","dctc2ydykv")</script><style>:root{--text-color:#343a40;--text-secondary-color:#6c757d;--background-color:#000;--secondary-background-color:#64ffda1a;--primary-color:#007bff;--secondary-color:#f8f9fa;--text-color-dark:#e4e6eb;--text-secondary-color-dark:#b0b3b8;--background-color-dark:#000000;--secondary-background-color-dark:#212529;--primary-color-dark:#ffffff;--secondary-color-dark:#212529}body{background-color:#000;font-size:1rem;font-weight:400;line-height:1.5;text-align:left}</style><meta name=description content><link rel=stylesheet href=/css/index.css><link rel=stylesheet href=/css/single.css><link rel=stylesheet href=/css/projects.css media=all><script defer src=/fontawesome-5/all-5.15.4.js></script><title>Hiding API keys from Git | JimBobBennett</title></head><body class=light onload=loading()><header><nav class="pt-3 navbar navbar-expand-lg"><div class="container-fluid mx-xs-2 mx-sm-5 mx-md-5 mx-lg-5"><a class="navbar-brand primary-font text-wrap" href=/><img src=/fav.png width=30 height=30 class="d-inline-block align-top">
JimBobBennett</a>
<button class=navbar-toggler type=button data-bs-toggle=collapse data-bs-target=#navbarContent aria-controls=navbarContent aria-expanded=false aria-label="Toggle navigation"><svg aria-hidden="true" height="24" viewBox="0 0 16 16" width="24" data-view-component="true"><path fill-rule="evenodd" d="M1 2.75A.75.75.0 011.75 2h12.5a.75.75.0 110 1.5H1.75A.75.75.0 011 2.75zm0 5A.75.75.0 011.75 7h12.5a.75.75.0 110 1.5H1.75A.75.75.0 011 7.75zM1.75 12a.75.75.0 100 1.5h12.5a.75.75.0 100-1.5H1.75z"/></svg></button><div class="collapse navbar-collapse text-wrap primary-font" id=navbarContent><ul class="navbar-nav ms-auto text-center"><li class="nav-item navbar-text"><a class=nav-link href=/ aria-label=home>Home</a></li><li class="nav-item navbar-text"><a class=nav-link href=/#about aria-label=about>About</a></li><li class="nav-item navbar-text"><a class=nav-link href=/#projects aria-label=projects>Recent Highlights</a></li><li class="nav-item navbar-text"><a class=nav-link href=/blogs title="Blog posts">Blog</a></li><li class="nav-item navbar-text"><a class=nav-link href=/videos title=Videos>Videos</a></li><li class="nav-item navbar-text"><a class=nav-link href=/livestreams title=Livestreams>Livestreams</a></li><li class="nav-item navbar-text"><a class=nav-link href=/conferences title=Conferences>Conferences</a></li><li class="nav-item navbar-text"><a class=nav-link href=/resume title=Resume>Resume</a></li></ul></div></div></nav></header><div id=content><section id=projects><div class="container pt-5" id=list-page><div class="row justify-content-center px-3 px-md-5"><h1 class="text-left pb-2 content">Hiding API keys from Git</h1><div class="text-left content">Jim Bennett
<small>|</small>
Dec 28, 2017</div></div></div></section><section id=single><div class=container><div class="row justify-content-center"><div class="col-sm-12 col-md-12 col-lg-9"><div class=pr-lg-4><article class="page-content p-2"><p>I&rsquo;ve been working on a <a href=/blogs/identifying-my-daughters-toys-using-ai/>Xamarin app using Azure Cognitive Services to do image recognition</a>, and one of the stumbling blocks I&rsquo;ve faced is what to do with my API keys. I want to make the app open source as an example of how to use these services, but don&rsquo;t want to check my API keys into Git to be available to all - after all, <a href=https://www.theregister.co.uk/2015/01/06/dev_blunder_shows_github_crawling_with_keyslurping_bots/>bad things can happen</a>.</p><p>I hit up twitter, and got a really awesome solution from <a href=https://twitter.com/bartlannoeye>Bart Lannoeye</a>:</p><blockquote class=twitter-tweet data-conversation=none data-lang=en><p lang=en dir=ltr>You can add the file with *your key here* then change locally and git update-index --assume-unchanged .\pathtofile. Shows file as unchanged => can't commit by accident. <a href="https://twitter.com/hashtag/protip?src=hash&ref_src=twsrc%5Etfw">#protip</a> We do the same for Kliva.</p>&mdash; Bart Lannoeye (@bartlannoeye) <a href="https://twitter.com/bartlannoeye/status/946437185372413952?ref_src=twsrc%5Etfw">December 28, 2017</a></blockquote><script async src=https://platform.twitter.com/widgets.js></script><p>This is exactly what I did, and it works perfectly. I&rsquo;ve created a static class called <code>ApiKeys</code> which contains all my keys using &ldquo;Your Key Here&rdquo; values:</p><pre tabindex=0><code>public static class ApiKeys
{
public static string PredictionKey = &#34;&lt;Your API Key&gt;&#34;;
public static Guid ProjectId = Guid.Parse(&#34;&lt;Your Project GUID&gt;&#34;);
}
</code></pre><p>I then added this to Git and commited. After my commit I ran:</p><pre tabindex=0><code>git update-index --assume-unchanged ./ApiKeys.cs
</code></pre><p>Done. I can then change the values to my actual API keys and Git doesn&rsquo;t see the change.</p><p>Obviously if I need to add any more keys to this file I&rsquo;d have to revert this change, remove all keys, add the new one with a &ldquo;your key&rdquo; type value, commit, re-run the update-index and put the keys back. A bit of work, but at least no worries about anyone abusing my API limits!</p><p>Thanks Bart!</p><hr><p><strong>Update - how to tell users what they need to do with this code</strong></p><p>I&rsquo;ve just had another great suggestion from <a href=https://developer.microsoft.com/en-gb/advocates/brandon-minnick>Brandon Minnick</a>, a fellow CDA here at Microsoft. He suggests adding a <code>#error</code> to the keys file so that when someone grabs the code and builds it they get an error telling them what to do, rather than a crash when the app is run:</p><pre tabindex=0><code>public static class ApiKeys
{
# error You need to set up your API keys.
// Start by registering for an account at https://customvision.ai
// Then create a new project.
// From the settings tab, find:
// Prediction Key
// Project Id
// and update the values below
public static string PredictionKey = &#34;&lt;Your Prediction Key&gt;&#34;;
public static Guid ProjectId = Guid.Parse(&#34;&lt;Your Project GUID&gt;&#34;);
}
</code></pre><hr><p><strong>Update 2 - how to fix it if you forget and add your keys</strong></p><p>Another great tip from <a href=https://developer.microsoft.com/en-gb/advocates/brandon-minnick>Brandon Minnick</a> is the <a href=https://rtyley.github.io/bfg-repo-cleaner/>BFG Repo-CLeaner</a>. If you accidentally checked in some API keys, this tool can remove them from the Git history.</p><p>Obviously it could be too late by the time you realize, so if you check any API keys in to a public repo you <strong>MUST</strong> regenerate them as there are <a href=http://www.timbroder.com/2015/01/my-2375-amazon-ec2-mistake.html>bots that can GitHub for API keys</a>. But this is good for a private repo that you are planning to make public or accidentally add personal keys to.</p></article></div></div><div class="col-sm-12 col-md-12 col-lg-3"><div class=sticky-sidebar><aside class=toc><h5>Table Of Contents</h5><div class=toc-content><nav id=TableOfContents></nav></div></aside><aside class=tags><h5>Tags</h5><ul class="tags-ul list-unstyled list-inline"><li class=list-inline-item><a href=https://jimbobbennett.dev/tags/azure target=_blank>azure</a></li><li class=list-inline-item><a href=https://jimbobbennett.dev/tags/technology target=_blank>technology</a></li><li class=list-inline-item><a href=https://jimbobbennett.dev/tags/api target=_blank>api</a></li><li class=list-inline-item><a href=https://jimbobbennett.dev/tags/keys target=_blank>keys</a></li></ul></aside></div></div></div><div class=row><div class="col-sm-12 col-md-12 col-lg-9 p-4"><div id=disqus_thread></div><script>var disqus_config=function(){this.page.url="https://jimbobbennett.dev/blogs/hiding-api-keys-from-git/",this.page.identifier="78d5d516394c6df579caaec81a98d8a0"};(function(){if(window.location.hostname=="localhost")return;var e=document,t=e.createElement("script");t.src="https://jimbobbennett.disqus.com/embed.js",t.setAttribute("data-timestamp",+new Date),(e.head||e.body).appendChild(t)})()</script><noscript>Please enable JavaScript to view the <a href=https://disqus.com/?ref_noscript>comments powered by Disqus.</a></noscript></div></div></div><button class="p-2 px-3" onclick=topFunction() id=topScroll>
<i class="fas fa-angle-up"></i></button></section><script>var topScroll=document.getElementById("topScroll");window.onscroll=function(){scrollFunction()};function scrollFunction(){document.body.scrollTop>20||document.documentElement.scrollTop>20?topScroll.style.display="block":topScroll.style.display="none"}function topFunction(){document.body.scrollTop=0,document.documentElement.scrollTop=0}</script></div><footer><div class="container py-4"><div class="row justify-content-center"><div class="col-md-4 text-center">&copy; 2023 All Rights Reserved</div></div></div></div></footer><script src=https://cdn.jsdelivr.net/npm/bootstrap@5.1.3/dist/js/bootstrap.min.js integrity=sha384-QJHtvGhmr9XOIpI6YVutG+2QOK9T+ZnN4kzFN1RtK3zEFEIsxhlmWl5/YESvpZ13 crossorigin=anonymous></script>
<script>document.body.className.includes("light")&&(document.body.classList.add("dark"),localStorage.setItem("pref-theme","dark"))</script><script>let loadingIcons;function loading(){myVar=setTimeout(showPage,100)}function showPage(){try{document.getElementById("loading-icons").style.display="block"}catch{}}</script><script>function createCopyButton(e,t){const n=document.createElement("button");n.className="copy-code-button",n.type="button",n.innerText="Copy",n.addEventListener("click",()=>copyCodeToClipboard(n,e,t)),addCopyButtonToDom(n,e)}async function copyCodeToClipboard(e,t,n){const s=t.querySelector("pre > code").innerText;try{n.writeText(s)}finally{codeWasCopied(e)}}function codeWasCopied(e){e.blur(),e.innerText="Copied!",setTimeout(function(){e.innerText="Copy"},2e3)}function addCopyButtonToDom(e,t){t.insertBefore(e,t.firstChild);const n=document.createElement("div");n.className="highlight-wrapper",t.parentNode.insertBefore(n,t),n.appendChild(t)}if(navigator&&navigator.clipboard)document.querySelectorAll(".highlight").forEach(e=>createCopyButton(e,navigator.clipboard));else{var script=document.createElement("script");script.src="https://cdnjs.cloudflare.com/ajax/libs/clipboard-polyfill/2.7.0/clipboard-polyfill.promise.js",script.integrity="sha256-waClS2re9NUbXRsryKoof+F9qc1gjjIhc2eT7ZbIv94=",script.crossOrigin="anonymous",script.onload=function(){addCopyButtons(clipboard)},document.querySelectorAll(".highlight").forEach(e=>createCopyButton(e,script)),document.body.appendChild(script)}</script></body></html>