├── Go
├── UserAssignedCosmosdb
│ ├── UserTableOutput.png
│ ├── index.html
│ ├── Dockerfile
│ ├── Gopkg.toml
│ ├── db.go
│ ├── main.go
│ ├── README.md
│ └── Gopkg.lock
├── UserAssignedKeyVault
│ ├── README.md
│ ├── Dockerfile
│ ├── Gopkg.toml
│ ├── main.go
│ └── Gopkg.lock
└── SystemAssignedBlobStorage
│ ├── Dockerfile
│ ├── Gopkg.toml
│ ├── main.go
│ ├── azstorage.go
│ ├── README.md
│ └── Gopkg.lock
├── CHANGELOG.md
├── Nodejs
└── UserAssignedKeyVault
│ ├── Dockerfile
│ ├── sample.js
│ └── README.md
├── README.md
├── .github
├── ISSUE_TEMPLATE.md
└── PULL_REQUEST_TEMPLATE.md
├── LICENSE.md
├── .gitignore
└── CONTRIBUTING.md
/Go/UserAssignedCosmosdb/UserTableOutput.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/Azure-Samples/aci-managed-identities/master/Go/UserAssignedCosmosdb/UserTableOutput.png
--------------------------------------------------------------------------------
/CHANGELOG.md:
--------------------------------------------------------------------------------
1 | ## [project-title] Changelog
2 |
3 |
4 | # x.y.z (yyyy-mm-dd)
5 |
6 | *Features*
7 | * ...
8 |
9 | *Bug Fixes*
10 | * ...
11 |
12 | *Breaking Changes*
13 | * ...
14 |
--------------------------------------------------------------------------------
/Nodejs/UserAssignedKeyVault/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM node:11.1.0
2 | WORKDIR /
3 | COPY ./sample.js /
4 | RUN npm install request-promise
5 | RUN npm install request
6 | RUN npm install azure-keyvault
7 |
8 | CMD ["sh", "-c", "node sample.js"]
9 |
--------------------------------------------------------------------------------
/Go/UserAssignedKeyVault/README.md:
--------------------------------------------------------------------------------
1 | # Using Managed Service Identities with Azure Container Instnace
2 |
3 | For a full walkthrough, check out the medium.com article [HERE](https://medium.com/@samkreter/managed-identities-with-azure-container-instance-golang-c98911206328)
4 |
--------------------------------------------------------------------------------
/Go/UserAssignedCosmosdb/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | {{.PageTitle}}
6 |
7 | {{range .Users}}
8 | - {{.Name}} - {{.Email}}
9 | {{end}}
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/Go/UserAssignedKeyVault/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM golang:1.9.2 as builder
2 | WORKDIR /go/src/msigolang/
3 | COPY . /go/src/msigolang/
4 | RUN go test ./... -v
5 | RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o run .
6 |
7 | FROM alpine:3.8
8 | RUN apk --update add ca-certificates
9 | WORKDIR /root/
10 | COPY --from=builder /go/src/msigolang/run .
11 | CMD ["./run"]
12 |
--------------------------------------------------------------------------------
/Go/SystemAssignedBlobStorage/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM golang:1.9.2 as builder
2 |
3 | RUN apt-get update && apt-get install -y unzip --no-install-recommends && \
4 | apt-get autoremove -y && apt-get clean -y && apt-get install -y curl
5 |
6 | RUN curl https://raw.githubusercontent.com/golang/dep/master/install.sh | sh
7 |
8 | WORKDIR /go/src/workdir/
9 |
10 | COPY Gopkg.toml Gopkg.lock ./
11 |
12 | RUN dep ensure -vendor-only
13 |
14 | COPY . /go/src/workdir/
15 | RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o getblob .
16 |
17 | FROM alpine:3.8
18 | RUN apk --update add ca-certificates
19 | WORKDIR /root/
20 | COPY --from=builder /go/src/workdir/getblob .
21 | CMD ["./getblob"]
--------------------------------------------------------------------------------
/Go/UserAssignedCosmosdb/Dockerfile:
--------------------------------------------------------------------------------
1 | FROM golang:1.9.2 as builder
2 |
3 | RUN apt-get update && apt-get install -y unzip --no-install-recommends && \
4 | apt-get autoremove -y && apt-get clean -y && apt-get install -y curl
5 |
6 | RUN curl https://raw.githubusercontent.com/golang/dep/master/install.sh | sh
7 |
8 | WORKDIR /go/src/workdir/
9 |
10 | COPY Gopkg.toml Gopkg.lock ./
11 |
12 | RUN dep ensure -vendor-only
13 |
14 | COPY . /go/src/workdir/
15 | #RUN go test ./... -v
16 | RUN CGO_ENABLED=0 GOOS=linux go build -a -installsuffix cgo -o run .
17 |
18 | FROM alpine:3.8
19 | RUN apk --update add ca-certificates
20 | WORKDIR /root/
21 | COPY --from=builder /go/src/workdir/run .
22 | COPY --from=builder /go/src/workdir/index.html .
23 | CMD ["./run"]
24 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Examples for Using Azure Container Instances with Managed Identites
2 |
3 | Examples in multiple langauges showing common senerios using Managed Identiteis for Azure Resources with ACI.
4 |
5 | ## Prerequisites
6 |
7 | - An Azure subscription. Get a [free trial here](https://azure.microsoft.com/en-us/free/)!
8 |
9 | ## Examples
10 |
11 | Here is a list of the provided examples:
12 |
13 | ### Go
14 | -------
15 |
16 | - UserAssignedCosmosdb - Use a user assigned identity to access data from [CosmosDB](https://docs.microsoft.com/en-us/azure/cosmos-db/introduction).
17 | - UserAssignedKeyVault - Use a user assigned identity to retrieve a secret from an [Azure Key Vault](https://azure.microsoft.com/en-us/services/key-vault/)
18 |
19 | ## Resources
20 |
21 | For details on contributing changes and information on this project's code of conduct, please refer to the [Contributing](CONTRIBUTING.md) file.
22 |
--------------------------------------------------------------------------------
/Go/UserAssignedKeyVault/Gopkg.toml:
--------------------------------------------------------------------------------
1 | # Gopkg.toml example
2 | #
3 | # Refer to https://golang.github.io/dep/docs/Gopkg.toml.html
4 | # for detailed Gopkg.toml documentation.
5 | #
6 | # required = ["github.com/user/thing/cmd/thing"]
7 | # ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
8 | #
9 | # [[constraint]]
10 | # name = "github.com/user/project"
11 | # version = "1.0.0"
12 | #
13 | # [[constraint]]
14 | # name = "github.com/user/project2"
15 | # branch = "dev"
16 | # source = "github.com/myfork/project2"
17 | #
18 | # [[override]]
19 | # name = "github.com/x/y"
20 | # version = "2.4.0"
21 | #
22 | # [prune]
23 | # non-go = false
24 | # go-tests = true
25 | # unused-packages = true
26 |
27 |
28 | [[constraint]]
29 | name = "github.com/Azure/azure-sdk-for-go"
30 | version = "21.3.0"
31 |
32 | [[constraint]]
33 | name = "github.com/Azure/go-autorest"
34 | version = "11.2.1"
35 |
36 | [prune]
37 | go-tests = true
38 | unused-packages = true
39 |
--------------------------------------------------------------------------------
/.github/ISSUE_TEMPLATE.md:
--------------------------------------------------------------------------------
1 |
4 | > Please provide us with the following information:
5 | > ---------------------------------------------------------------
6 |
7 | ### This issue is for a: (mark with an `x`)
8 | ```
9 | - [ ] bug report -> please search issues before submitting
10 | - [ ] feature request
11 | - [ ] documentation issue or request
12 | - [ ] regression (a behavior that used to work and stopped in a new release)
13 | ```
14 |
15 | ### Minimal steps to reproduce
16 | >
17 |
18 | ### Any log messages given by the failure
19 | >
20 |
21 | ### Expected/desired behavior
22 | >
23 |
24 | ### OS and Version?
25 | > Windows 7, 8 or 10. Linux (which distribution). macOS (Yosemite? El Capitan? Sierra?)
26 |
27 | ### Versions
28 | >
29 |
30 | ### Mention any other details that might be useful
31 |
32 | > ---------------------------------------------------------------
33 | > Thanks! We'll be in touch soon.
34 |
--------------------------------------------------------------------------------
/Go/SystemAssignedBlobStorage/Gopkg.toml:
--------------------------------------------------------------------------------
1 | # Gopkg.toml example
2 | #
3 | # Refer to https://golang.github.io/dep/docs/Gopkg.toml.html
4 | # for detailed Gopkg.toml documentation.
5 | #
6 | # required = ["github.com/user/thing/cmd/thing"]
7 | # ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
8 | #
9 | # [[constraint]]
10 | # name = "github.com/user/project"
11 | # version = "1.0.0"
12 | #
13 | # [[constraint]]
14 | # name = "github.com/user/project2"
15 | # branch = "dev"
16 | # source = "github.com/myfork/project2"
17 | #
18 | # [[override]]
19 | # name = "github.com/x/y"
20 | # version = "2.4.0"
21 | #
22 | # [prune]
23 | # non-go = false
24 | # go-tests = true
25 | # unused-packages = true
26 |
27 |
28 | [[constraint]]
29 | name = "github.com/Azure/azure-storage-blob-go"
30 | version = "0.2.0"
31 |
32 | [[constraint]]
33 | name = "github.com/Azure/go-autorest"
34 | version = "11.2.6"
35 |
36 | [prune]
37 | go-tests = true
38 | unused-packages = true
39 |
40 | [[constraint]]
41 | name = "github.com/Azure/azure-sdk-for-go"
42 | version = "22.0.0"
43 |
--------------------------------------------------------------------------------
/.github/PULL_REQUEST_TEMPLATE.md:
--------------------------------------------------------------------------------
1 | ## Purpose
2 |
3 | * ...
4 |
5 | ## Does this introduce a breaking change?
6 |
7 | ```
8 | [ ] Yes
9 | [ ] No
10 | ```
11 |
12 | ## Pull Request Type
13 | What kind of change does this Pull Request introduce?
14 |
15 |
16 | ```
17 | [ ] Bugfix
18 | [ ] Feature
19 | [ ] Code style update (formatting, local variables)
20 | [ ] Refactoring (no functional changes, no api changes)
21 | [ ] Documentation content changes
22 | [ ] Other... Please describe:
23 | ```
24 |
25 | ## How to Test
26 | * Get the code
27 |
28 | ```
29 | git clone [repo-address]
30 | cd [repo-name]
31 | git checkout [branch-name]
32 | npm install
33 | ```
34 |
35 | * Test the code
36 |
37 | ```
38 | ```
39 |
40 | ## What to Check
41 | Verify that the following are valid
42 | * ...
43 |
44 | ## Other Information
45 |
--------------------------------------------------------------------------------
/Go/UserAssignedCosmosdb/Gopkg.toml:
--------------------------------------------------------------------------------
1 | # Gopkg.toml example
2 | #
3 | # Refer to https://github.com/golang/dep/blob/master/docs/Gopkg.toml.md
4 | # for detailed Gopkg.toml documentation.
5 | #
6 | # required = ["github.com/user/thing/cmd/thing"]
7 | # ignored = ["github.com/user/project/pkgX", "bitbucket.org/user/project/pkgA/pkgY"]
8 | #
9 | # [[constraint]]
10 | # name = "github.com/user/project"
11 | # version = "1.0.0"
12 | #
13 | # [[constraint]]
14 | # name = "github.com/user/project2"
15 | # branch = "dev"
16 | # source = "github.com/myfork/project2"
17 | #
18 | # [[override]]
19 | # name = "github.com/x/y"
20 | # version = "2.4.0"
21 | #
22 | # [prune]
23 | # non-go = false
24 | # go-tests = true
25 | # unused-packages = true
26 |
27 |
28 | [[constraint]]
29 | name = "github.com/Azure/azure-sdk-for-go"
30 | version = "22.0.0"
31 |
32 | [[constraint]]
33 | name = "github.com/Azure/go-autorest"
34 | version = "11.2.6"
35 |
36 | [[constraint]]
37 | branch = "master"
38 | name = "github.com/globalsign/mgo"
39 |
40 | [[constraint]]
41 | branch = "master"
42 | name = "github.com/icrowley/fake"
43 |
44 | [prune]
45 | go-tests = true
46 | unused-packages = true
47 |
--------------------------------------------------------------------------------
/LICENSE.md:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) Microsoft Corporation. All rights reserved.
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE
--------------------------------------------------------------------------------
/Nodejs/UserAssignedKeyVault/sample.js:
--------------------------------------------------------------------------------
1 | var rp = require('request-promise');
2 | var KeyVault = require('azure-keyvault');
3 | var keyVaultName = process.env.KEY_VAULT_NAME;
4 | var secretName = process.env.SECRET_NAME;
5 | var secretVersion = process.env.SECRET_VERSION;
6 |
7 | var options = {
8 | uri: 'http://169.254.169.254/metadata/identity/oauth2/token',
9 | qs: {
10 | 'api-version': '2018-02-01',
11 | 'resource': 'https://vault.azure.net',
12 | },
13 | headers: {
14 | 'Metadata': 'true'
15 | },
16 | json: true // Automatically parses the JSON string in the response
17 | };
18 |
19 | rp(options).then(function (tokenResponse) {
20 | var authenticator = function (challenge, callback) {
21 | var authorizationValue = tokenResponse.token_type + ' ' + tokenResponse.access_token;
22 | return callback(null, authorizationValue);
23 | };
24 |
25 | var credentials = new KeyVault.KeyVaultCredentials(authenticator);
26 | var client = new KeyVault.KeyVaultClient(credentials);
27 |
28 | client.getSecret(`https://${keyVaultName}.vault.azure.net`, secretName, secretVersion).then((secretBundle) => {
29 | console.log(`The secret value is: ${secretBundle.value}`)
30 | }).catch((err) => {
31 | console.log(err)
32 | });
33 | }).catch(function (err) {
34 | console.log(err)
35 | });
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Byte-compiled / optimized / DLL files
2 | __pycache__/
3 | *.py[cod]
4 | *$py.class
5 |
6 | # C extensions
7 | *.so
8 |
9 | # Distribution / packaging
10 | .Python
11 | build/
12 | develop-eggs/
13 | dist/
14 | downloads/
15 | eggs/
16 | .eggs/
17 | lib/
18 | lib64/
19 | parts/
20 | sdist/
21 | var/
22 | wheels/
23 | *.egg-info/
24 | .installed.cfg
25 | *.egg
26 | MANIFEST
27 |
28 | # PyInstaller
29 | # Usually these files are written by a python script from a template
30 | # before PyInstaller builds the exe, so as to inject date/other infos into it.
31 | *.manifest
32 | *.spec
33 |
34 | # Installer logs
35 | pip-log.txt
36 | pip-delete-this-directory.txt
37 |
38 | # Unit test / coverage reports
39 | htmlcov/
40 | .tox/
41 | .coverage
42 | .coverage.*
43 | .cache
44 | nosetests.xml
45 | coverage.xml
46 | *.cover
47 | .hypothesis/
48 | .pytest_cache/
49 |
50 | # Translations
51 | *.mo
52 | *.pot
53 |
54 | # Django stuff:
55 | *.log
56 | local_settings.py
57 | db.sqlite3
58 |
59 | # Flask stuff:
60 | instance/
61 | .webassets-cache
62 |
63 | # Scrapy stuff:
64 | .scrapy
65 |
66 | # Sphinx documentation
67 | docs/_build/
68 |
69 | # PyBuilder
70 | target/
71 |
72 | # Jupyter Notebook
73 | .ipynb_checkpoints
74 |
75 | # pyenv
76 | .python-version
77 |
78 | # celery beat schedule file
79 | celerybeat-schedule
80 |
81 | # SageMath parsed files
82 | *.sage.py
83 |
84 | # Environments
85 | .env
86 | .venv
87 | env/
88 | venv/
89 | ENV/
90 | env.bak/
91 | venv.bak/
92 |
93 | # Spyder project settings
94 | .spyderproject
95 | .spyproject
96 |
97 | # Rope project settings
98 | .ropeproject
99 |
100 | # mkdocs documentation
101 | /site
102 |
103 | # mypy
104 | .mypy_cache/
105 |
--------------------------------------------------------------------------------
/Go/SystemAssignedBlobStorage/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "context"
5 | "fmt"
6 | "log"
7 | "os"
8 | "strings"
9 | "time"
10 | )
11 |
12 | const (
13 | maxRetries = 10
14 | errMaxRetriesReachedTemplate = "exceeded retry limit: %v"
15 | containerName = "testdata"
16 | blobName = "testfile.txt"
17 | )
18 |
19 | func main() {
20 | storageAccountID := getEnv("STORAGE_ACCOUNT_ID")
21 |
22 | resourceIDSplit := strings.Split(storageAccountID, "/")
23 | if len(resourceIDSplit) < 9 {
24 | log.Fatal("Invalid resource ID.")
25 | }
26 |
27 | azStorage, err := NewAzStorage(resourceIDSplit[8], resourceIDSplit[4], resourceIDSplit[2], "")
28 | if err != nil {
29 | log.Fatal(err)
30 | }
31 |
32 | ctx, cancel := context.WithTimeout(context.Background(), time.Second*20)
33 | defer cancel()
34 |
35 | var blobContents string
36 |
37 | err = DoRetry(func(attempt int) (retry bool, err error) {
38 | blobContents, err = azStorage.GetBlob(ctx, containerName, blobName)
39 | return true, err
40 | })
41 | if err != nil {
42 | log.Fatal(err)
43 | }
44 |
45 | log.Println("Download Blob Contents:")
46 | time.Sleep(time.Second * 1)
47 | fmt.Println(blobContents)
48 |
49 | blocker := make(chan struct{})
50 | <-blocker
51 | }
52 |
53 | func getEnv(envName string) string {
54 | val, ok := os.LookupEnv(envName)
55 | if !ok {
56 | log.Fatalf("%s must be set.", envName)
57 | }
58 |
59 | return val
60 | }
61 |
62 | type retryFunc func(attempt int) (retry bool, err error)
63 |
64 | // DoRetry keeps trying the function until the second argument
65 | // returns false, or no error is returned.
66 | func DoRetry(fn retryFunc) error {
67 | var err error
68 | var cont bool
69 | attempt := 1
70 | for {
71 | cont, err = fn(attempt)
72 | if !cont || err == nil {
73 | break
74 | }
75 | attempt++
76 | if attempt > maxRetries {
77 | return fmt.Errorf(errMaxRetriesReachedTemplate, err)
78 | }
79 | }
80 | return err
81 | }
82 |
--------------------------------------------------------------------------------
/Go/UserAssignedKeyVault/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "context"
5 | "fmt"
6 | "log"
7 | "os"
8 | "strings"
9 |
10 | "github.com/Azure/azure-sdk-for-go/services/keyvault/2016-10-01/keyvault"
11 | "github.com/Azure/go-autorest/autorest/azure"
12 | "github.com/Azure/go-autorest/autorest/azure/auth"
13 | )
14 |
15 | func main() {
16 | vaultName, ok := os.LookupEnv("KEYVAULT_VAULT_NAME")
17 | if !ok {
18 | log.Fatal("KEYVAULT_VAULT_NAME must be set.")
19 | }
20 |
21 | secretName, ok := os.LookupEnv("KEYVAULT_SECRET_NAME")
22 | if !ok {
23 | log.Fatal("KEYVAULT_SECRET_NAME must be set.")
24 | }
25 |
26 | clientID := os.Getenv("MSI_USER_ASSIGNED_CLIENTID")
27 |
28 | keyClient, err := NewKeyVaultClient(vaultName, clientID)
29 | if err != nil {
30 | log.Fatal(err)
31 | }
32 |
33 | secret, err := keyClient.GetSecret(secretName)
34 | if err != nil {
35 | log.Fatal(err)
36 | }
37 |
38 | log.Printf("Retrieved secret '%s' from keyvault using MSI", secret)
39 | }
40 |
41 | // KeyVault holds the information for a keyvault instance
42 | type KeyVault struct {
43 | client *keyvault.BaseClient
44 | vaultURL string
45 | }
46 |
47 | // NewKeyVaultClient creates a new keyvault client
48 | func NewKeyVaultClient(vaultName, clientID string) (*KeyVault, error) {
49 | msiKeyConfig := &auth.MSIConfig{
50 | Resource: strings.TrimSuffix(azure.PublicCloud.KeyVaultEndpoint, "/"),
51 | ClientID: clientID,
52 | }
53 |
54 | auth, err := msiKeyConfig.Authorizer()
55 | if err != nil {
56 | return nil, err
57 | }
58 |
59 | keyClient := keyvault.New()
60 | keyClient.Authorizer = auth
61 |
62 | k := &KeyVault{
63 | vaultURL: fmt.Sprintf("https://%s.%s", vaultName, azure.PublicCloud.KeyVaultDNSSuffix),
64 | client: &keyClient,
65 | }
66 |
67 | return k, nil
68 | }
69 |
70 | // GetSecret retrieves a secret from keyvault
71 | func (k *KeyVault) GetSecret(keyName string) (string, error) {
72 | ctx := context.Background()
73 |
74 | keyBundle, err := k.client.GetSecret(ctx, k.vaultURL, keyName, "")
75 | if err != nil {
76 | return "", err
77 | }
78 |
79 | return *keyBundle.Value, nil
80 | }
81 |
--------------------------------------------------------------------------------
/Go/UserAssignedCosmosdb/db.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "crypto/tls"
5 | "fmt"
6 | "log"
7 | "net"
8 |
9 | "github.com/globalsign/mgo"
10 | "github.com/globalsign/mgo/bson"
11 | "github.com/icrowley/fake"
12 | )
13 |
14 | // User holds inforamtion about a user
15 | type User struct {
16 | Name string `json:"name"`
17 | Email string `json:"email"`
18 | }
19 |
20 | // DB is the database wrapper for a mongodb connection
21 | type DB struct {
22 | connURI string
23 | Container string
24 | }
25 |
26 | // NewDB creates a new database wrapper
27 | func NewDB(connURI, container string) *DB {
28 | return &DB{
29 | connURI: connURI,
30 | Container: container,
31 | }
32 | }
33 |
34 | func (db *DB) getConn() *mgo.Session {
35 | dialInfo, err := mgo.ParseURL(db.connURI)
36 | if err != nil {
37 | log.Fatal(err)
38 | }
39 |
40 | // //Below part is similar to above.
41 | dialInfo.DialServer = func(addr *mgo.ServerAddr) (net.Conn, error) {
42 | return tls.Dial("tcp", addr.String(), &tls.Config{})
43 | }
44 |
45 | session, err := mgo.DialWithInfo(dialInfo)
46 | if err != nil {
47 | log.Fatal(err)
48 | }
49 |
50 | session.SetSafe(&mgo.Safe{})
51 |
52 | return session
53 | }
54 |
55 | // InsertUsers inserts the passed in users into the database.
56 | func (db *DB) InsertUsers(users []User) error {
57 | session := db.getConn()
58 | defer session.Close()
59 |
60 | c := session.DB(db.Container).C(db.Container)
61 |
62 | log.Println("Adding Recored to Databases")
63 |
64 | errOccured := false
65 |
66 | for idx := range users {
67 | //Container started the work
68 | err := c.Insert(&users[idx])
69 | if err != nil {
70 | errOccured = true
71 | log.Printf("Error while inserting user: %v", err)
72 | }
73 | }
74 |
75 | if errOccured {
76 | return fmt.Errorf("1 or more errors occured while inserting users into db")
77 | }
78 |
79 | return nil
80 | }
81 |
82 | // GetUsers gets all of the users from the database.
83 | func (db *DB) GetUsers() ([]User, error) {
84 | session := db.getConn()
85 | defer session.Close()
86 |
87 | c := session.DB(db.Container).C(db.Container)
88 |
89 | log.Println("Getting Users from Databases")
90 |
91 | var users []User
92 | err := c.Find(bson.M{}).All(&users)
93 | if err != nil {
94 | return nil, err
95 | }
96 |
97 | return users, nil
98 | }
99 |
100 | // PopulateWithUsers generates and adds the passed in number of users to the database.
101 | func (db *DB) PopulateWithUsers(numUsers int) error {
102 | users := generateFakeUsers(numUsers)
103 |
104 | return db.InsertUsers(users)
105 | }
106 |
107 | func generateFakeUsers(num int) []User {
108 | users := make([]User, 0, num)
109 | for i := 0; i < num; i++ {
110 | users = append(users, User{
111 | Name: fake.FirstName(),
112 | Email: fake.EmailAddress(),
113 | })
114 | }
115 |
116 | return users
117 | }
118 |
--------------------------------------------------------------------------------
/Go/SystemAssignedBlobStorage/azstorage.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "context"
5 | "fmt"
6 | "io/ioutil"
7 | "log"
8 | "net/url"
9 |
10 | "github.com/Azure/azure-sdk-for-go/services/storage/mgmt/2017-06-01/storage"
11 | "github.com/Azure/azure-storage-blob-go/2016-05-31/azblob"
12 | "github.com/Azure/go-autorest/autorest/azure/auth"
13 | )
14 |
15 | var (
16 | blobFormatString = `https://%s.blob.core.windows.net`
17 | )
18 |
19 | // AzStorage object to interact with azure storage
20 | type AzStorage struct {
21 | StorageAccountName string
22 | ResourceGroupName string
23 | SubscriptionID string
24 | DefaultBlobName string
25 | DefaultContainerName string
26 | }
27 |
28 | // NewAzStorage creates a new client to interact with azure storage
29 | func NewAzStorage(storageAccountName, resourceGroupName, subscriptionID, defaultContainerName string) (*AzStorage, error) {
30 | return &AzStorage{
31 | StorageAccountName: storageAccountName,
32 | ResourceGroupName: resourceGroupName,
33 | SubscriptionID: subscriptionID,
34 | DefaultContainerName: defaultContainerName,
35 | }, nil
36 | }
37 |
38 | // GetBlob downloads the specified blob contents
39 | func (c *AzStorage) GetBlob(ctx context.Context, containerName, blobName string) (string, error) {
40 | b := c.getBlobURL(ctx, containerName, blobName)
41 |
42 | resp, err := b.GetBlob(ctx, azblob.BlobRange{}, azblob.BlobAccessConditions{}, false)
43 | if err != nil {
44 | return "", err
45 | }
46 | defer resp.Body().Close()
47 | body, err := ioutil.ReadAll(resp.Body())
48 | return string(body), err
49 | }
50 |
51 | func (c *AzStorage) getBlobURL(ctx context.Context, containerName, blobName string) azblob.BlobURL {
52 | container := c.getContainerURL(ctx, containerName)
53 | blob := container.NewBlobURL(blobName)
54 | return blob
55 | }
56 |
57 | func (c *AzStorage) getContainerURL(ctx context.Context, containerName string) azblob.ContainerURL {
58 | key, err := c.getAccountPrimaryKey(ctx)
59 | if err != nil {
60 | log.Fatal(err)
61 | }
62 |
63 | cred := azblob.NewSharedKeyCredential(c.StorageAccountName, key)
64 | p := azblob.NewPipeline(cred, azblob.PipelineOptions{})
65 |
66 | u, _ := url.Parse(fmt.Sprintf(blobFormatString, c.StorageAccountName))
67 | service := azblob.NewServiceURL(*u, p)
68 | container := service.NewContainerURL(containerName)
69 | return container
70 | }
71 |
72 | func (c *AzStorage) getAccountPrimaryKey(ctx context.Context) (string, error) {
73 | accountsClient, err := c.getStorageAccountsClient()
74 | if err != nil {
75 | return "", err
76 | }
77 |
78 | result, err := accountsClient.ListKeys(ctx, c.ResourceGroupName, c.StorageAccountName)
79 | if err != nil {
80 | return "", err
81 | }
82 |
83 | return *(((*result.Keys)[0]).Value), nil
84 | }
85 |
86 | func (c *AzStorage) getStorageAccountsClient() (*storage.AccountsClient, error) {
87 | storageAccountsClient := storage.NewAccountsClient(c.SubscriptionID)
88 |
89 | msiConfig := auth.NewMSIConfig()
90 |
91 | auth, err := msiConfig.Authorizer()
92 | if err != nil {
93 | return nil, err
94 | }
95 |
96 | storageAccountsClient.Authorizer = auth
97 |
98 | return &storageAccountsClient, nil
99 | }
100 |
--------------------------------------------------------------------------------
/Go/UserAssignedCosmosdb/main.go:
--------------------------------------------------------------------------------
1 | package main
2 |
3 | import (
4 | "context"
5 | "fmt"
6 | "html/template"
7 | "log"
8 | "net/http"
9 | "os"
10 | "strings"
11 | "time"
12 |
13 | "github.com/Azure/azure-sdk-for-go/services/keyvault/2016-10-01/keyvault"
14 | "github.com/Azure/go-autorest/autorest/azure"
15 | "github.com/Azure/go-autorest/autorest/azure/auth"
16 | )
17 |
18 | const (
19 | getSecretRetires = 10
20 | cosmosDBURISecretName = "cosmosDBConnectionString"
21 | )
22 |
23 | func main() {
24 | vaultName, ok := os.LookupEnv("VAULT_NAME")
25 | if !ok {
26 | log.Fatal("VAULT_NAME must be set.")
27 | }
28 |
29 | clientID, ok := os.LookupEnv("MSI_CLIENTID")
30 | if !ok {
31 | log.Fatal("MSI_CLIENTID must be set.")
32 | }
33 |
34 | keyClient, err := NewKeyVaultClient(vaultName, clientID)
35 | if err != nil {
36 | log.Fatal(err)
37 | }
38 |
39 | count := 0
40 | var dbURI string
41 | for {
42 | dbURI, err = keyClient.GetSecret(cosmosDBURISecretName)
43 | if err != nil {
44 | if count > getSecretRetires {
45 | log.Fatalf("Failed to get secret within retries with err: %v", err)
46 | }
47 |
48 | log.Printf("Retrying GetSecret: %d", count)
49 | count++
50 |
51 | time.Sleep(time.Second)
52 | continue
53 | }
54 |
55 | log.Println("Got DBURI")
56 | break
57 | }
58 |
59 | db := NewDB(dbURI, "users")
60 | users, err := db.GetUsers()
61 | if err != nil {
62 | log.Fatal(err)
63 | }
64 |
65 | // if theres no users in the DB, generate some and add them in
66 | if len(users) == 0 {
67 | err := db.PopulateWithUsers(10)
68 | if err != nil {
69 | log.Fatal(err)
70 | }
71 |
72 | users, err = db.GetUsers()
73 | if err != nil {
74 | log.Fatal(err)
75 | }
76 | }
77 |
78 | tmpl := template.Must(template.ParseFiles("index.html"))
79 |
80 | http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
81 | data := IndexPageData{
82 | PageTitle: "All the Users",
83 | Users: users,
84 | }
85 | tmpl.Execute(w, data)
86 | })
87 |
88 | log.Println("Serving on port 80")
89 | log.Fatal(http.ListenAndServe("0.0.0.0:80", nil))
90 | }
91 |
92 | // IndexPageData holds the data to populate index.html
93 | type IndexPageData struct {
94 | PageTitle string
95 | Users []User
96 | }
97 |
98 | // KeyVault holds the information for a keyvault instance
99 | type KeyVault struct {
100 | client *keyvault.BaseClient
101 | vaultURL string
102 | }
103 |
104 | // NewKeyVaultClient creates a new keyvault client
105 | func NewKeyVaultClient(vaultName, clientID string) (*KeyVault, error) {
106 | msiKeyConfig := &auth.MSIConfig{
107 | Resource: strings.TrimSuffix(azure.PublicCloud.KeyVaultEndpoint, "/"),
108 | ClientID: clientID,
109 | }
110 |
111 | auth, err := msiKeyConfig.Authorizer()
112 | if err != nil {
113 | return nil, err
114 | }
115 |
116 | keyClient := keyvault.New()
117 | keyClient.Authorizer = auth
118 |
119 | k := &KeyVault{
120 | vaultURL: fmt.Sprintf("https://%s.%s", vaultName, azure.PublicCloud.KeyVaultDNSSuffix),
121 | client: &keyClient,
122 | }
123 |
124 | return k, nil
125 | }
126 |
127 | // GetSecret retrieves a secret from keyvault
128 | func (k *KeyVault) GetSecret(keyName string) (string, error) {
129 | ctx := context.Background()
130 |
131 | keyBundle, err := k.client.GetSecret(ctx, k.vaultURL, keyName, "")
132 | if err != nil {
133 | return "", err
134 | }
135 |
136 | return *keyBundle.Value, nil
137 | }
138 |
--------------------------------------------------------------------------------
/Go/SystemAssignedBlobStorage/README.md:
--------------------------------------------------------------------------------
1 | # Access Blob Storage from Azure Container Instances Using Manged Identites
2 |
3 | This example walksthrough how to access an Azure Blob Storage from Azure Container Instances. The best part of all, absolutly no access credentials needed.
4 |
5 | ## Prerequisites
6 |
7 | - An Azure subscription. Get a [free trial here](https://azure.microsoft.com/en-us/free/)!
8 |
9 | - A [DockerHub](http://dockerhub.com) or other container registry account.
10 |
11 | - A machine with Docker installed
12 |
13 | ## Getting Started
14 |
15 | ### Build and Push the Image
16 |
17 | First up is to build and push our container to a container registry e.g. Dockerhub, Azure Container Registry
18 |
19 | 1. On a machine with docker installed, run the following command in this directory with the Dockerfile to build the container image
20 |
21 | ```sh
22 | docker build -t /msi-blob:0.0.1 .
23 | ```
24 |
25 | The above command will install all the dependencies into the container. The first time you run this is will take a while to download all of the dependencies but will be much faster once it is cached.
26 |
27 | 2. Push the image to [DockerHub](http://dockerhub.com)
28 |
29 | ```sh
30 | docker push /msi-msi-blob:0.0.1
31 | ```
32 |
33 | ### Setting Up the Azure Resources
34 |
35 | To deploy the container, open either a terminal with the Azure CLI installed or check out [CloudShell](https://shell.azure.com/) for a ready-to-go option
36 |
37 | First, lets set up some environment variables to make these commands nicer to copy and paste
38 |
39 | ```sh
40 | DOCKER_IMAGE_NAME="" #This is the image name you pushed to dockerhub
41 | RESOURCE_GROUP="" #If this doesn't exist we will create one
42 | STORAGE_ACCOUNT="" #This must be all lowercase or numbers, no special characters
43 | ```
44 |
45 | Create a resource group.
46 |
47 | az group create --name $RESOURCE_GROUP --location westus
48 |
49 | ### Setup the Azure Storage Account
50 |
51 | 1. Create the storage account
52 |
53 | az storage account create -g $RESOURCE_GROUP -n $STORAGE_ACCOUNT
54 |
55 | 2. Let's save the storage account ID and Key for later
56 |
57 | STORAGE_KEY=$(az storage account keys list -g $RESOURCE_GROUP -n $STORAGE_ACCOUNT --query [0].value | tr -d '"')
58 |
59 | STORAGE_ACCOUNT_ID=$(az storage account show -g $RESOURCE_GROUP -n $STORAGE_ACCOUNT --query id | tr -d '"')
60 |
61 | 3. Create a blob container inside the storage account
62 |
63 | az storage container create -n testdata --account-name $STORAGE_ACCOUNT --account-key $STORAGE_KEY
64 |
65 | 4. Upload a simple file to the blob. If you don't have a text file handy simply run: `echo "hello from blob storage!" > ./testfile.txt`
66 |
67 | az storage blob upload -c testdata -n testfile.txt -f ./testfile.txt --account-name $STORAGE_ACCOUNT --account-key $STORAGE_KEY
68 |
69 | ### Time to Deploy to Azure Container Instances
70 |
71 | Now we can use the single deploy command for ACI, make sure to change to the correct image name below:
72 |
73 | ```sh
74 | az container create \
75 | --resource-group $RESOURCE_GROUP \
76 | --name msi-blob \
77 | -e STORAGE_ACCOUNT_ID=$STORAGE_ACCOUNT_ID \
78 | --image $DOCKER_IMAGE_NAME \
79 | --assign-identity --scope $STORAGE_ACCOUNT_ID
80 | ```
81 |
82 | The above command will create the container instance and set up everything needed for the system assigned Managed Identities.
83 |
84 | Finally, once the command finished, check the log output to see the text file:
85 |
86 | az container logs -g $RESOURCE_GROUP -n msi-blob
87 |
88 | That should be a good start to never needing to store production credentials again.
89 |
90 | ## Issues
91 |
92 | If you have any issues or find any mistakes, Please open an Issue on this repository and we will update this document.
93 |
--------------------------------------------------------------------------------
/CONTRIBUTING.md:
--------------------------------------------------------------------------------
1 | # Contributing to [project-title]
2 |
3 | This project welcomes contributions and suggestions. Most contributions require you to agree to a
4 | Contributor License Agreement (CLA) declaring that you have the right to, and actually do, grant us
5 | the rights to use your contribution. For details, visit https://cla.microsoft.com.
6 |
7 | When you submit a pull request, a CLA-bot will automatically determine whether you need to provide
8 | a CLA and decorate the PR appropriately (e.g., label, comment). Simply follow the instructions
9 | provided by the bot. You will only need to do this once across all repos using our CLA.
10 |
11 | This project has adopted the [Microsoft Open Source Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
12 | For more information see the [Code of Conduct FAQ](https://opensource.microsoft.com/codeofconduct/faq/) or
13 | contact [opencode@microsoft.com](mailto:opencode@microsoft.com) with any additional questions or comments.
14 |
15 | - [Code of Conduct](#coc)
16 | - [Issues and Bugs](#issue)
17 | - [Feature Requests](#feature)
18 | - [Submission Guidelines](#submit)
19 |
20 | ## Code of Conduct
21 | Help us keep this project open and inclusive. Please read and follow our [Code of Conduct](https://opensource.microsoft.com/codeofconduct/).
22 |
23 | ## Found an Issue?
24 | If you find a bug in the source code or a mistake in the documentation, you can help us by
25 | [submitting an issue](#submit-issue) to the GitHub Repository. Even better, you can
26 | [submit a Pull Request](#submit-pr) with a fix.
27 |
28 | ## Want a Feature?
29 | You can *request* a new feature by [submitting an issue](#submit-issue) to the GitHub
30 | Repository. If you would like to *implement* a new feature, please submit an issue with
31 | a proposal for your work first, to be sure that we can use it.
32 |
33 | * **Small Features** can be crafted and directly [submitted as a Pull Request](#submit-pr).
34 |
35 | ## Submission Guidelines
36 |
37 | ### Submitting an Issue
38 | Before you submit an issue, search the archive, maybe your question was already answered.
39 |
40 | If your issue appears to be a bug, and hasn't been reported, open a new issue.
41 | Help us to maximize the effort we can spend fixing issues and adding new
42 | features, by not reporting duplicate issues. Providing the following information will increase the
43 | chances of your issue being dealt with quickly:
44 |
45 | * **Overview of the Issue** - if an error is being thrown a non-minified stack trace helps
46 | * **Version** - what version is affected (e.g. 0.1.2)
47 | * **Motivation for or Use Case** - explain what are you trying to do and why the current behavior is a bug for you
48 | * **Browsers and Operating System** - is this a problem with all browsers?
49 | * **Reproduce the Error** - provide a live example or a unambiguous set of steps
50 | * **Related Issues** - has a similar issue been reported before?
51 | * **Suggest a Fix** - if you can't fix the bug yourself, perhaps you can point to what might be
52 | causing the problem (line of code or commit)
53 |
54 | You can file new issues by providing the above information at the corresponding repository's issues link: https://github.com/[organization-name]/[repository-name]/issues/new].
55 |
56 | ### Submitting a Pull Request (PR)
57 | Before you submit your Pull Request (PR) consider the following guidelines:
58 |
59 | * Search the repository (https://github.com/[organization-name]/[repository-name]/pulls) for an open or closed PR
60 | that relates to your submission. You don't want to duplicate effort.
61 |
62 | * Make your changes in a new git fork:
63 |
64 | * Commit your changes using a descriptive commit message
65 | * Push your fork to GitHub:
66 | * In GitHub, create a pull request
67 | * If we suggest changes then:
68 | * Make the required updates.
69 | * Rebase your fork and force push to your GitHub repository (this will update your Pull Request):
70 |
71 | ```shell
72 | git rebase master -i
73 | git push -f
74 | ```
75 |
76 | That's it! Thank you for your contribution!
77 |
--------------------------------------------------------------------------------
/Nodejs/UserAssignedKeyVault/README.md:
--------------------------------------------------------------------------------
1 | # Access KeyVault from Azure Container Instances Using Manged Identites
2 |
3 | This example walks through how to get a secret from key vault. But no more passing tokens or credentials to your application to access key vault. We're going to be using Managed Identites for Azure Resources instead.
4 |
5 | Our sample will retrieve the secret from key vault and log it.
6 |
7 | ## Prerequisites
8 |
9 | - An Azure subscription. Get a [free trial here](https://azure.microsoft.com/en-us/free/)!
10 |
11 | - A [DockerHub](http://dockerhub.com) or other container registry account.
12 |
13 | - A machine with Docker installed
14 |
15 | ## Getting Started
16 |
17 | ### Build and Push the Image
18 |
19 | First up is to build and push our container to a container registry e.g. Dockerhub, Azure Container Registry
20 |
21 | 1. On a machine with docker installed, run the following command in this directory with the Dockerfile to build the container image
22 |
23 | ```sh
24 | docker build -t /msi-nodejs:0.0.1 .
25 | ```
26 |
27 | The above command will install all the dependencies into the container. The first time you run this is will take a while to download all of the dependencies but will be much faster once it is cached.
28 |
29 | 2. Push the image to [DockerHub](http://dockerhub.com)
30 |
31 | ```sh
32 | docker push /msi-nodejs:0.0.1
33 | ```
34 |
35 | ### Setting Up the Azure Resources
36 |
37 | To deploy the container, open either a terminal with the Azure CLI installed or check out [CloudShell](https://shell.azure.com/) for a ready-to-go option
38 |
39 | First, lets set up some environment variables to make these commands nicer to copy and paste
40 |
41 | ```sh
42 | DOCKER_IMAGE_NAME="" #This is the image name you pushed to dockerhub
43 | RESOURCE_GROUP="" #If this doesn't exist we will create one
44 | KEYVAULT_NAME=""
45 | SECRET_NAME=""
46 | SECRET_VERSION="secretVersion>"
47 | USER_ASSIGNED_IDENTITY_NAME=""
48 | ```
49 |
50 | ### Create a resource group.
51 |
52 | az group create --name $RESOURCE_GROUP --location westus
53 |
54 | #### Create the User Assigned Identity
55 |
56 | Next we create a user assigned identity. Once we create and add the permissions, we will be able to use this for multiple container groups.
57 |
58 | The following commands will create the identity and get the needed information from it.
59 |
60 | CLIENT_ID=$(az identity create -g $RESOURCE_GROUP --name $USER_ASSIGNED_IDENTITY_NAME --query clientId | tr -d '"')
61 | PRINCIPAL_ID=$(az identity show -g $RESOURCE_GROUP --name $USER_ASSIGNED_IDENTITY_NAME --query principalId | tr -d '"')
62 | MSI_RESOURCE_ID=$(az identity show -g $RESOURCE_GROUP --name $USER_ASSIGNED_IDENTITY_NAME --query id | tr -d '"')
63 |
64 | #### Create a Key Vault and Set the Permissions
65 |
66 | If you don’t already have a Key Vault create, use the following command to create one:
67 |
68 | az keyvault create -g $RESOURCE_GROUP --name $KEYVAULT_NAME
69 |
70 | Now we create a secret in KeyVault
71 |
72 | SECRET_VERSION=$(az keyvault secret set --name $SECRET_NAME --value --vault-name $KEYVAULT_NAME | cut -d'/' -f6 | tr -d '"')
73 |
74 | Now, we can give our identity access to the Key Vault
75 |
76 | az keyvault set-policy -n $KEYVAULT_NAME --object-id $PRINCIPAL_ID -g $RESOURCE_GROUP --secret-permissions get
77 |
78 | The above command uses the environment variable we set to give our identity “get” permission for secrets in the Key Vault
79 |
80 | ### Time to Deploy to Azure Container Instances
81 |
82 | Now we can use the single deploy command for ACI, make sure to change to the correct image name below:
83 |
84 | ```sh
85 | az container create \
86 | --resource-group $RESOURCE_GROUP \
87 | --name msi-nodejs \
88 | -e KEY_VAULT_NAME=$KEY_VAULT_NAME SECRET_NAME=$SECRET_NAME SECRET_VERSION=$SECRET_VERSION \
89 | --image $DOCKER_IMAGE_NAME \
90 | --assign-identity $MSI_RESOURCE_ID
91 | ```
92 |
93 | The above command will create the container instance and set up everything needed for Managed Identities.
94 |
95 | Once the command has finished, we can run the below command to get the container logs which output the secret value :
96 |
97 | ```sh
98 | az container logs --resource-group $RESOURCE_GROUP --name msi-nodejs
99 | ```
100 | The result will be: "The secret value is: XXXX"
101 |
102 | ## Issues
103 |
104 | If you have any issues or find any mistakes, Please open an Issue on this repository and we will update this document.
105 |
--------------------------------------------------------------------------------
/Go/UserAssignedKeyVault/Gopkg.lock:
--------------------------------------------------------------------------------
1 | # This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
2 |
3 |
4 | [[projects]]
5 | name = "contrib.go.opencensus.io/exporter/ocagent"
6 | packages = ["."]
7 | revision = "00af367e65149ff1f2f4b93bbfbb84fd9297170d"
8 | version = "v0.2.0"
9 |
10 | [[projects]]
11 | name = "github.com/Azure/azure-sdk-for-go"
12 | packages = [
13 | "services/keyvault/2016-10-01/keyvault",
14 | "version"
15 | ]
16 | revision = "da91af54816b4cf72949c225a2d0980f51fab01b"
17 | version = "v21.3.0"
18 |
19 | [[projects]]
20 | name = "github.com/Azure/go-autorest"
21 | packages = [
22 | "autorest",
23 | "autorest/adal",
24 | "autorest/azure",
25 | "autorest/azure/auth",
26 | "autorest/azure/cli",
27 | "autorest/date",
28 | "autorest/to",
29 | "autorest/validation",
30 | "logger",
31 | "tracing",
32 | "version"
33 | ]
34 | revision = "a27e7666341d6b0509d868c713b91dae08971382"
35 | version = "v11.2.1"
36 |
37 | [[projects]]
38 | name = "github.com/census-instrumentation/opencensus-proto"
39 | packages = [
40 | "gen-go/agent/common/v1",
41 | "gen-go/agent/trace/v1",
42 | "gen-go/trace/v1"
43 | ]
44 | revision = "24333298e36590ea0716598caacc8959fc393c48"
45 | version = "v0.0.2"
46 |
47 | [[projects]]
48 | name = "github.com/dgrijalva/jwt-go"
49 | packages = ["."]
50 | revision = "06ea1031745cb8b3dab3f6a236daf2b0aa468b7e"
51 | version = "v3.2.0"
52 |
53 | [[projects]]
54 | name = "github.com/dimchansky/utfbom"
55 | packages = ["."]
56 | revision = "5448fe645cb1964ba70ac8f9f2ffe975e61a536c"
57 | version = "v1.0.0"
58 |
59 | [[projects]]
60 | name = "github.com/golang/protobuf"
61 | packages = [
62 | "proto",
63 | "ptypes",
64 | "ptypes/any",
65 | "ptypes/duration",
66 | "ptypes/timestamp",
67 | "ptypes/wrappers"
68 | ]
69 | revision = "aa810b61a9c79d51363740d207bb46cf8e620ed5"
70 | version = "v1.2.0"
71 |
72 | [[projects]]
73 | name = "github.com/mitchellh/go-homedir"
74 | packages = ["."]
75 | revision = "ae18d6b8b3205b561c79e8e5f69bff09736185f4"
76 | version = "v1.0.0"
77 |
78 | [[projects]]
79 | branch = "master"
80 | name = "go.opencensus.io"
81 | packages = [
82 | ".",
83 | "exemplar",
84 | "internal",
85 | "internal/tagencoding",
86 | "plugin/ochttp",
87 | "plugin/ochttp/propagation/b3",
88 | "plugin/ochttp/propagation/tracecontext",
89 | "stats",
90 | "stats/internal",
91 | "stats/view",
92 | "tag",
93 | "trace",
94 | "trace/internal",
95 | "trace/propagation",
96 | "trace/tracestate"
97 | ]
98 | revision = "486d66aed0ffe5d13ed9f0d59f96fa761cd0abcf"
99 |
100 | [[projects]]
101 | branch = "master"
102 | name = "golang.org/x/crypto"
103 | packages = [
104 | "pkcs12",
105 | "pkcs12/internal/rc2"
106 | ]
107 | revision = "0c41d7ab0a0ee717d4590a44bcb987dfd9e183eb"
108 |
109 | [[projects]]
110 | branch = "master"
111 | name = "golang.org/x/net"
112 | packages = [
113 | "context",
114 | "http/httpguts",
115 | "http2",
116 | "http2/hpack",
117 | "idna",
118 | "internal/timeseries",
119 | "trace"
120 | ]
121 | revision = "04a2e542c03f1d053ab3e4d6e5abcd4b66e2be8e"
122 |
123 | [[projects]]
124 | branch = "master"
125 | name = "golang.org/x/sync"
126 | packages = ["semaphore"]
127 | revision = "1d60e4601c6fd243af51cc01ddf169918a5407ca"
128 |
129 | [[projects]]
130 | branch = "master"
131 | name = "golang.org/x/sys"
132 | packages = ["unix"]
133 | revision = "8a28ead16f52c8aaeffbf79239b251dfdf6c4f96"
134 |
135 | [[projects]]
136 | name = "golang.org/x/text"
137 | packages = [
138 | "collate",
139 | "collate/build",
140 | "internal/colltab",
141 | "internal/gen",
142 | "internal/tag",
143 | "internal/triegen",
144 | "internal/ucd",
145 | "language",
146 | "secure/bidirule",
147 | "transform",
148 | "unicode/bidi",
149 | "unicode/cldr",
150 | "unicode/norm",
151 | "unicode/rangetable"
152 | ]
153 | revision = "f21a4dfb5e38f5895301dc265a8def02365cc3d0"
154 | version = "v0.3.0"
155 |
156 | [[projects]]
157 | branch = "master"
158 | name = "google.golang.org/api"
159 | packages = ["support/bundler"]
160 | revision = "a2651947f503a1793446d4058bb073a6fdf99e53"
161 |
162 | [[projects]]
163 | branch = "master"
164 | name = "google.golang.org/genproto"
165 | packages = ["googleapis/rpc/status"]
166 | revision = "94acd270e44e65579b9ee3cdab25034d33fed608"
167 |
168 | [[projects]]
169 | name = "google.golang.org/grpc"
170 | packages = [
171 | ".",
172 | "balancer",
173 | "balancer/base",
174 | "balancer/roundrobin",
175 | "codes",
176 | "connectivity",
177 | "credentials",
178 | "encoding",
179 | "encoding/proto",
180 | "grpclog",
181 | "internal",
182 | "internal/backoff",
183 | "internal/channelz",
184 | "internal/envconfig",
185 | "internal/grpcrand",
186 | "internal/transport",
187 | "keepalive",
188 | "metadata",
189 | "naming",
190 | "peer",
191 | "resolver",
192 | "resolver/dns",
193 | "resolver/passthrough",
194 | "stats",
195 | "status",
196 | "tap"
197 | ]
198 | revision = "8dea3dc473e90c8179e519d91302d0597c0ca1d1"
199 | version = "v1.15.0"
200 |
201 | [solve-meta]
202 | analyzer-name = "dep"
203 | analyzer-version = 1
204 | inputs-digest = "9c3f021f412eb8539557127aec16c2d68b060ae1ed83cc2f6c2315b51de9ce66"
205 | solver-name = "gps-cdcl"
206 | solver-version = 1
207 |
--------------------------------------------------------------------------------
/Go/UserAssignedCosmosdb/README.md:
--------------------------------------------------------------------------------
1 | # Access CosmosDB from Azure Container Instances Using Manged Identites
2 |
3 | This example walks through how to get and display a list a users from a CosmosDB Mongo database. But no more passing secrets or credentials to your application. We're going to be using Managed Identites for Azure Resources instead. This is going to allow us to securly get all of the secrets we want (in this case a cosmosDB connection string) from an Azure Key Vault.
4 |
5 | Our final output should be a webpage that looks something like this:
6 |
7 | 
8 |
9 | It's not the prettiest but should show just how powerful Azure Container Instances with Managed Identities can be.
10 |
11 | ## Prerequisites
12 |
13 | - An Azure subscription. Get a [free trial here](https://azure.microsoft.com/en-us/free/)!
14 |
15 | - A [DockerHub](http://dockerhub.com) or other container registry account.
16 |
17 | - A machine with Docker installed
18 |
19 | ## Getting Started
20 |
21 | ### Build and Push the Image
22 |
23 | First up is to build and push our container to a container registry e.g. Dockerhub, Azure Container Registry
24 |
25 | 1. On a machine with docker installed, run the following command in this directory with the Dockerfile to build the container image
26 |
27 | ```sh
28 | docker build -t /msi-cosmosdb:0.0.1 .
29 | ```
30 |
31 | The above command will install all the dependencies into the container. The first time you run this is will take a while to download all of the dependencies but will be much faster once it is cached.
32 |
33 | 2. Push the image to [DockerHub](http://dockerhub.com)
34 |
35 | ```sh
36 | docker push /msi-cosmosdb:0.0.1
37 | ```
38 |
39 | ### Setting Up the Azure Resources
40 |
41 | To deploy the container, open either a terminal with the Azure CLI installed or check out [CloudShell](https://shell.azure.com/) for a ready-to-go option
42 |
43 | First, lets set up some environment variables to make these commands nicer to copy and paste
44 |
45 | ```sh
46 | DOCKER_IMAGE_NAME="" #This is the image name you pushed to dockerhub
47 | RESOURCE_GROUP="" #If this doesn't exist we will create one
48 | COMOSDB_ACCOUNT_NAME="" #This must be all lowercase
49 | KEYVAULT_NAME=""
50 | USER_ASSIGNED_IDENTITY_NAME=""
51 | ```
52 |
53 | Create a resource group.
54 |
55 | az group create --name $RESOURCE_GROUP --location westus
56 |
57 | #### Create a CosmosDB Mongo Database
58 |
59 | Create a CosmosDB with the MongoDB API. Make sure the name is all lowercase
60 |
61 | az cosmosdb create -g $RESOURCE_GROUP --name $COMOSDB_ACCOUNT_NAME --kind MongoDB
62 |
63 | The above command will take a few minutes to finish creating the database.
64 |
65 | THe following command will get the secret connection string and remove the ssl=true which is required for our mongo golang driver
66 |
67 | CONNECTION_STRING=$(az cosmosdb list-connection-strings -g $RESOURCE_GROUP -n $COMOSDB_ACCOUNT_NAME --query connectionStrings[0].connectionString |sed -e "s/\/?ssl=true//")
68 |
69 | #### Create the User Assigned Identity
70 |
71 | Next we create a user assigned identity. Once we create and add the permissions, we will be able to use this for multiple container groups.
72 |
73 | The following commands will create the identity and get the needed information from it.
74 |
75 | CLIENT_ID=$(az identity create -g $RESOURCE_GROUP --name $USER_ASSIGNED_IDENTITY_NAME --query clientId | tr -d '"')
76 | PRINCIPAL_ID=$(az identity show -g $RESOURCE_GROUP --name $USER_ASSIGNED_IDENTITY_NAME --query principalId | tr -d '"')
77 | MSI_RESOURCE_ID=$(az identity show -g $RESOURCE_GROUP --name $USER_ASSIGNED_IDENTITY_NAME --query id | tr -d '"')
78 |
79 | #### Create a Key Vault and Set the Permissions
80 |
81 | If you don’t already have a Key Vault create, use the following command to create one:
82 |
83 | az keyvault create -g $RESOURCE_GROUP --name $KEYVAULT_NAME
84 |
85 | Now we can add our connection string we got earlier as a secret in KeyVault
86 |
87 | az keyvault secret set --name cosmosDBConnectionString --value $CONNECTION_STRING --vault-name $KEYVAULT_NAME
88 |
89 | Now, we can give our identity access to the Key Vault
90 |
91 | az keyvault set-policy -n $KEYVAULT_NAME --object-id $PRINCIPAL_ID -g $RESOURCE_GROUP --secret-permissions get
92 |
93 | The above command uses the environment variable we set to give our identity “get” permission for secrets in the Key Vault
94 |
95 | ### Time to Deploy to Azure Container Instances
96 |
97 | Now we can use the single deploy command for ACI, make sure to change to the correct image name below:
98 |
99 | ```sh
100 | az container create \
101 | --resource-group $RESOURCE_GROUP \
102 | --name msi-cosmosdb \
103 | --ip-address public \
104 | -e VAULT_NAME=$KEYVAULT_NAME MSI_CLIENTID=$CLIENT_ID \
105 | --image $DOCKER_IMAGE_NAME \
106 | --assign-identity $MSI_RESOURCE_ID \
107 | --query ipAddress.ip
108 | ```
109 |
110 | The above command will create the container instance and set up everything needed for Managed Identities.
111 |
112 | Once the command has finished, you should see the public IP Address for the container group. Go to the address and you should see something that looks like the following:
113 |
114 | 
115 |
116 | That should be a good start to never needing to store production credentials again.
117 |
118 | ## Issues
119 |
120 | If you have any issues or find any mistakes, Please open an Issue on this repository and we will update this document.
121 |
--------------------------------------------------------------------------------
/Go/SystemAssignedBlobStorage/Gopkg.lock:
--------------------------------------------------------------------------------
1 | # This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
2 |
3 |
4 | [[projects]]
5 | name = "contrib.go.opencensus.io/exporter/ocagent"
6 | packages = ["."]
7 | revision = "00af367e65149ff1f2f4b93bbfbb84fd9297170d"
8 | version = "v0.2.0"
9 |
10 | [[projects]]
11 | name = "github.com/Azure/azure-pipeline-go"
12 | packages = ["pipeline"]
13 | revision = "b8e3409182fd52e74f7d7bdfbff5833591b3b655"
14 | version = "v0.1.8"
15 |
16 | [[projects]]
17 | name = "github.com/Azure/azure-sdk-for-go"
18 | packages = [
19 | "services/storage/mgmt/2017-06-01/storage",
20 | "version"
21 | ]
22 | revision = "ca4654c50e30248fa542c1f0dd07fbde21d9b9a2"
23 | version = "v22.0.0"
24 |
25 | [[projects]]
26 | name = "github.com/Azure/azure-storage-blob-go"
27 | packages = ["2016-05-31/azblob"]
28 | revision = "bb46532f68b79e9e1baca8fb19a382ef5d40ed33"
29 | version = "0.2.0"
30 |
31 | [[projects]]
32 | name = "github.com/Azure/go-autorest"
33 | packages = [
34 | "autorest",
35 | "autorest/adal",
36 | "autorest/azure",
37 | "autorest/azure/auth",
38 | "autorest/azure/cli",
39 | "autorest/date",
40 | "autorest/validation",
41 | "logger",
42 | "tracing",
43 | "version"
44 | ]
45 | revision = "4e5fffdf007df29ed0862f9e01fafabf4396e851"
46 | version = "v11.2.6"
47 |
48 | [[projects]]
49 | name = "github.com/census-instrumentation/opencensus-proto"
50 | packages = [
51 | "gen-go/agent/common/v1",
52 | "gen-go/agent/trace/v1",
53 | "gen-go/trace/v1"
54 | ]
55 | revision = "24333298e36590ea0716598caacc8959fc393c48"
56 | version = "v0.0.2"
57 |
58 | [[projects]]
59 | name = "github.com/dgrijalva/jwt-go"
60 | packages = ["."]
61 | revision = "06ea1031745cb8b3dab3f6a236daf2b0aa468b7e"
62 | version = "v3.2.0"
63 |
64 | [[projects]]
65 | name = "github.com/dimchansky/utfbom"
66 | packages = ["."]
67 | revision = "5448fe645cb1964ba70ac8f9f2ffe975e61a536c"
68 | version = "v1.0.0"
69 |
70 | [[projects]]
71 | name = "github.com/golang/protobuf"
72 | packages = [
73 | "proto",
74 | "ptypes",
75 | "ptypes/any",
76 | "ptypes/duration",
77 | "ptypes/timestamp",
78 | "ptypes/wrappers"
79 | ]
80 | revision = "aa810b61a9c79d51363740d207bb46cf8e620ed5"
81 | version = "v1.2.0"
82 |
83 | [[projects]]
84 | name = "github.com/mitchellh/go-homedir"
85 | packages = ["."]
86 | revision = "ae18d6b8b3205b561c79e8e5f69bff09736185f4"
87 | version = "v1.0.0"
88 |
89 | [[projects]]
90 | name = "go.opencensus.io"
91 | packages = [
92 | ".",
93 | "exemplar",
94 | "internal",
95 | "internal/tagencoding",
96 | "plugin/ochttp",
97 | "plugin/ochttp/propagation/b3",
98 | "plugin/ochttp/propagation/tracecontext",
99 | "stats",
100 | "stats/internal",
101 | "stats/view",
102 | "tag",
103 | "trace",
104 | "trace/internal",
105 | "trace/propagation",
106 | "trace/tracestate"
107 | ]
108 | revision = "b7bf3cdb64150a8c8c53b769fdeb2ba581bd4d4b"
109 | version = "v0.18.0"
110 |
111 | [[projects]]
112 | branch = "master"
113 | name = "golang.org/x/crypto"
114 | packages = [
115 | "pkcs12",
116 | "pkcs12/internal/rc2"
117 | ]
118 | revision = "4d3f4d9ffa16a13f451c3b2999e9c49e9750bf06"
119 |
120 | [[projects]]
121 | branch = "master"
122 | name = "golang.org/x/net"
123 | packages = [
124 | "context",
125 | "http/httpguts",
126 | "http2",
127 | "http2/hpack",
128 | "idna",
129 | "internal/timeseries",
130 | "trace"
131 | ]
132 | revision = "e11730110bbd884bbf19550bfafe9d69519ce29e"
133 |
134 | [[projects]]
135 | branch = "master"
136 | name = "golang.org/x/sync"
137 | packages = ["semaphore"]
138 | revision = "1d60e4601c6fd243af51cc01ddf169918a5407ca"
139 |
140 | [[projects]]
141 | branch = "master"
142 | name = "golang.org/x/sys"
143 | packages = ["unix"]
144 | revision = "9b800f95dbbc54abff0acf7ee32d88ba4e328c89"
145 |
146 | [[projects]]
147 | name = "golang.org/x/text"
148 | packages = [
149 | "collate",
150 | "collate/build",
151 | "internal/colltab",
152 | "internal/gen",
153 | "internal/tag",
154 | "internal/triegen",
155 | "internal/ucd",
156 | "language",
157 | "secure/bidirule",
158 | "transform",
159 | "unicode/bidi",
160 | "unicode/cldr",
161 | "unicode/norm",
162 | "unicode/rangetable"
163 | ]
164 | revision = "f21a4dfb5e38f5895301dc265a8def02365cc3d0"
165 | version = "v0.3.0"
166 |
167 | [[projects]]
168 | branch = "master"
169 | name = "google.golang.org/api"
170 | packages = ["support/bundler"]
171 | revision = "799fe93f827439cfd251917066a18691dc6a7fc1"
172 |
173 | [[projects]]
174 | branch = "master"
175 | name = "google.golang.org/genproto"
176 | packages = ["googleapis/rpc/status"]
177 | revision = "c830210a61dfaa790e1920f8d0470fc27bc2efbe"
178 |
179 | [[projects]]
180 | name = "google.golang.org/grpc"
181 | packages = [
182 | ".",
183 | "balancer",
184 | "balancer/base",
185 | "balancer/roundrobin",
186 | "codes",
187 | "connectivity",
188 | "credentials",
189 | "encoding",
190 | "encoding/proto",
191 | "grpclog",
192 | "internal",
193 | "internal/backoff",
194 | "internal/channelz",
195 | "internal/envconfig",
196 | "internal/grpcrand",
197 | "internal/transport",
198 | "keepalive",
199 | "metadata",
200 | "naming",
201 | "peer",
202 | "resolver",
203 | "resolver/dns",
204 | "resolver/passthrough",
205 | "stats",
206 | "status",
207 | "tap"
208 | ]
209 | revision = "2e463a05d100327ca47ac218281906921038fd95"
210 | version = "v1.16.0"
211 |
212 | [solve-meta]
213 | analyzer-name = "dep"
214 | analyzer-version = 1
215 | inputs-digest = "dd53ea681956063dabf9e7f43d1bbd63e1fff87b50c29ec64de2d239bfad6135"
216 | solver-name = "gps-cdcl"
217 | solver-version = 1
218 |
--------------------------------------------------------------------------------
/Go/UserAssignedCosmosdb/Gopkg.lock:
--------------------------------------------------------------------------------
1 | # This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'.
2 |
3 |
4 | [[projects]]
5 | name = "contrib.go.opencensus.io/exporter/ocagent"
6 | packages = ["."]
7 | revision = "00af367e65149ff1f2f4b93bbfbb84fd9297170d"
8 | version = "v0.2.0"
9 |
10 | [[projects]]
11 | name = "github.com/Azure/azure-sdk-for-go"
12 | packages = [
13 | "services/keyvault/2016-10-01/keyvault",
14 | "version"
15 | ]
16 | revision = "ca4654c50e30248fa542c1f0dd07fbde21d9b9a2"
17 | version = "v22.0.0"
18 |
19 | [[projects]]
20 | name = "github.com/Azure/go-autorest"
21 | packages = [
22 | "autorest",
23 | "autorest/adal",
24 | "autorest/azure",
25 | "autorest/azure/auth",
26 | "autorest/azure/cli",
27 | "autorest/date",
28 | "autorest/to",
29 | "autorest/validation",
30 | "logger",
31 | "tracing",
32 | "version"
33 | ]
34 | revision = "4e5fffdf007df29ed0862f9e01fafabf4396e851"
35 | version = "v11.2.6"
36 |
37 | [[projects]]
38 | name = "github.com/census-instrumentation/opencensus-proto"
39 | packages = [
40 | "gen-go/agent/common/v1",
41 | "gen-go/agent/trace/v1",
42 | "gen-go/trace/v1"
43 | ]
44 | revision = "24333298e36590ea0716598caacc8959fc393c48"
45 | version = "v0.0.2"
46 |
47 | [[projects]]
48 | branch = "master"
49 | name = "github.com/corpix/uarand"
50 | packages = ["."]
51 | revision = "2b8494104d86337cdd41d0a49cbed8e4583c0ab4"
52 |
53 | [[projects]]
54 | name = "github.com/dgrijalva/jwt-go"
55 | packages = ["."]
56 | revision = "06ea1031745cb8b3dab3f6a236daf2b0aa468b7e"
57 | version = "v3.2.0"
58 |
59 | [[projects]]
60 | name = "github.com/dimchansky/utfbom"
61 | packages = ["."]
62 | revision = "5448fe645cb1964ba70ac8f9f2ffe975e61a536c"
63 | version = "v1.0.0"
64 |
65 | [[projects]]
66 | branch = "master"
67 | name = "github.com/globalsign/mgo"
68 | packages = [
69 | ".",
70 | "bson",
71 | "internal/json",
72 | "internal/sasl",
73 | "internal/scram"
74 | ]
75 | revision = "eeefdecb41b842af6dc652aaea4026e8403e62df"
76 |
77 | [[projects]]
78 | name = "github.com/golang/protobuf"
79 | packages = [
80 | "proto",
81 | "ptypes",
82 | "ptypes/any",
83 | "ptypes/duration",
84 | "ptypes/timestamp",
85 | "ptypes/wrappers"
86 | ]
87 | revision = "aa810b61a9c79d51363740d207bb46cf8e620ed5"
88 | version = "v1.2.0"
89 |
90 | [[projects]]
91 | branch = "master"
92 | name = "github.com/icrowley/fake"
93 | packages = ["."]
94 | revision = "4178557ae428460c3780a381c824a1f3aceb6325"
95 |
96 | [[projects]]
97 | name = "github.com/mitchellh/go-homedir"
98 | packages = ["."]
99 | revision = "ae18d6b8b3205b561c79e8e5f69bff09736185f4"
100 | version = "v1.0.0"
101 |
102 | [[projects]]
103 | name = "go.opencensus.io"
104 | packages = [
105 | ".",
106 | "exemplar",
107 | "internal",
108 | "internal/tagencoding",
109 | "plugin/ochttp",
110 | "plugin/ochttp/propagation/b3",
111 | "plugin/ochttp/propagation/tracecontext",
112 | "stats",
113 | "stats/internal",
114 | "stats/view",
115 | "tag",
116 | "trace",
117 | "trace/internal",
118 | "trace/propagation",
119 | "trace/tracestate"
120 | ]
121 | revision = "b7bf3cdb64150a8c8c53b769fdeb2ba581bd4d4b"
122 | version = "v0.18.0"
123 |
124 | [[projects]]
125 | branch = "master"
126 | name = "golang.org/x/crypto"
127 | packages = [
128 | "pkcs12",
129 | "pkcs12/internal/rc2"
130 | ]
131 | revision = "4d3f4d9ffa16a13f451c3b2999e9c49e9750bf06"
132 |
133 | [[projects]]
134 | branch = "master"
135 | name = "golang.org/x/net"
136 | packages = [
137 | "context",
138 | "http/httpguts",
139 | "http2",
140 | "http2/hpack",
141 | "idna",
142 | "internal/timeseries",
143 | "trace"
144 | ]
145 | revision = "e11730110bbd884bbf19550bfafe9d69519ce29e"
146 |
147 | [[projects]]
148 | branch = "master"
149 | name = "golang.org/x/sync"
150 | packages = ["semaphore"]
151 | revision = "1d60e4601c6fd243af51cc01ddf169918a5407ca"
152 |
153 | [[projects]]
154 | branch = "master"
155 | name = "golang.org/x/sys"
156 | packages = ["unix"]
157 | revision = "9b800f95dbbc54abff0acf7ee32d88ba4e328c89"
158 |
159 | [[projects]]
160 | name = "golang.org/x/text"
161 | packages = [
162 | "collate",
163 | "collate/build",
164 | "internal/colltab",
165 | "internal/gen",
166 | "internal/tag",
167 | "internal/triegen",
168 | "internal/ucd",
169 | "language",
170 | "secure/bidirule",
171 | "transform",
172 | "unicode/bidi",
173 | "unicode/cldr",
174 | "unicode/norm",
175 | "unicode/rangetable"
176 | ]
177 | revision = "f21a4dfb5e38f5895301dc265a8def02365cc3d0"
178 | version = "v0.3.0"
179 |
180 | [[projects]]
181 | branch = "master"
182 | name = "google.golang.org/api"
183 | packages = ["support/bundler"]
184 | revision = "45a606955d1cf544236717b0ba3a7beca40b0b37"
185 |
186 | [[projects]]
187 | branch = "master"
188 | name = "google.golang.org/genproto"
189 | packages = ["googleapis/rpc/status"]
190 | revision = "c830210a61dfaa790e1920f8d0470fc27bc2efbe"
191 |
192 | [[projects]]
193 | name = "google.golang.org/grpc"
194 | packages = [
195 | ".",
196 | "balancer",
197 | "balancer/base",
198 | "balancer/roundrobin",
199 | "codes",
200 | "connectivity",
201 | "credentials",
202 | "encoding",
203 | "encoding/proto",
204 | "grpclog",
205 | "internal",
206 | "internal/backoff",
207 | "internal/channelz",
208 | "internal/envconfig",
209 | "internal/grpcrand",
210 | "internal/transport",
211 | "keepalive",
212 | "metadata",
213 | "naming",
214 | "peer",
215 | "resolver",
216 | "resolver/dns",
217 | "resolver/passthrough",
218 | "stats",
219 | "status",
220 | "tap"
221 | ]
222 | revision = "2e463a05d100327ca47ac218281906921038fd95"
223 | version = "v1.16.0"
224 |
225 | [solve-meta]
226 | analyzer-name = "dep"
227 | analyzer-version = 1
228 | inputs-digest = "00b731570cdada18428e9849f6f12316197b20517fa61ceb1e9a2952b98e0a05"
229 | solver-name = "gps-cdcl"
230 | solver-version = 1
231 |
--------------------------------------------------------------------------------