diff --git a/docs/book/src/topics/language-specific-examples/azure-identity-sdk.md b/docs/book/src/topics/language-specific-examples/azure-identity-sdk.md index c9f8501..b736113 100644 --- a/docs/book/src/topics/language-specific-examples/azure-identity-sdk.md +++ b/docs/book/src/topics/language-specific-examples/azure-identity-sdk.md @@ -2,13 +2,13 @@ The following client libraries are the **minimum** version required -| Language | Library | Minimum Version | -| --------------------- | --------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------------- | -| Go | N/A | N/A | -| C# | [azure-sdk-for-net](https://github.com/Azure/azure-sdk-for-net) | [Azure.Identity_1.5.0](https://github.com/Azure/azure-sdk-for-net/releases/tag/Azure.Identity_1.5.0) | -| JavaScript/TypeScript | [azure-sdk-for-js](https://github.com/Azure/azure-sdk-for-js) | [@azure/identity_2.0.0](https://github.com/Azure/azure-sdk-for-js/releases/tag/@azure/identity_2.0.0) | -| Python | [azure-sdk-for-python](https://github.com/Azure/azure-sdk-for-python) | [azure-identity_1.7.0](https://github.com/Azure/azure-sdk-for-python/releases/tag/azure-identity_1.7.0) | -| Java | [azure-sdk-for-java](https://github.com/Azure/azure-sdk-for-java) | [azure-identity_1.4.0](https://github.com/Azure/azure-sdk-for-java/releases/tag/azure-identity_1.4.0) | +| Language | Library | Minimum Version | +| --------------------- | --------------------------------------------------------------------- | ----------------------------------------------------------------------------------------------------------------------- | +| Go | [azure-sdk-for-go](https://github.com/Azure/azure-sdk-for-go) | [sdk/azidentity/v1.3.0-beta.1](https://github.com/Azure/azure-sdk-for-go/releases/tag/sdk%2Fazidentity%2Fv1.3.0-beta.1) | +| C# | [azure-sdk-for-net](https://github.com/Azure/azure-sdk-for-net) | [Azure.Identity_1.5.0](https://github.com/Azure/azure-sdk-for-net/releases/tag/Azure.Identity_1.5.0) | +| JavaScript/TypeScript | [azure-sdk-for-js](https://github.com/Azure/azure-sdk-for-js) | [@azure/identity_2.0.0](https://github.com/Azure/azure-sdk-for-js/releases/tag/@azure/identity_2.0.0) | +| Python | [azure-sdk-for-python](https://github.com/Azure/azure-sdk-for-python) | [azure-identity_1.7.0](https://github.com/Azure/azure-sdk-for-python/releases/tag/azure-identity_1.7.0) | +| Java | [azure-sdk-for-java](https://github.com/Azure/azure-sdk-for-java) | [azure-identity_1.4.0](https://github.com/Azure/azure-sdk-for-java/releases/tag/azure-identity_1.4.0) | ## Examples @@ -16,6 +16,7 @@ The following client libraries are the **minimum** version required | Language | Library | Example | | --------------------- | --------------------------------------------------------------------- | ------------------------------------------------------------------------------------------------- | +| Go | [azure-sdk-for-go](https://github.com/Azure/azure-sdk-for-go) | [Link](https://github.com/Azure/azure-workload-identity/tree/main/examples/azure-identity/go) | | Python | [azure-sdk-for-python](https://github.com/Azure/azure-sdk-for-python) | [Link](https://github.com/Azure/azure-workload-identity/tree/main/examples/azure-identity/python) | | JavaScript/TypeScript | [azure-sdk-for-js](https://github.com/Azure/azure-sdk-for-js) | [Link](https://github.com/Azure/azure-workload-identity/tree/main/examples/azure-identity/node) | | C# | [azure-sdk-for-net](https://github.com/Azure/azure-sdk-for-net) | [Link](https://github.com/Azure/azure-workload-identity/tree/main/examples/azure-identity/dotnet) | diff --git a/examples/azure-identity/go/Dockerfile b/examples/azure-identity/go/Dockerfile new file mode 100644 index 0000000..b1aedc1 --- /dev/null +++ b/examples/azure-identity/go/Dockerfile @@ -0,0 +1,29 @@ +ARG BUILDER=mcr.microsoft.com/oss/go/microsoft/golang:1.19-bullseye +ARG BASEIMAGE=gcr.io/distroless/static:nonroot + +FROM ${BUILDER} as builder + +WORKDIR /workspace +# Copy the Go Modules manifests +COPY go.mod go.mod +COPY go.sum go.sum +# cache deps before building and copying source so that we don't need to re-download as much +# and so that source changes don't invalidate our downloaded layer +RUN go mod download + +# Copy the go source +COPY main.go main.go + +# Build +ARG TARGETARCH +RUN CGO_ENABLED=0 GOOS=linux GOARCH=${TARGETARCH} GO111MODULE=on go build -a -o azidgo . + +# Use distroless as minimal base image to package the manager binary +# Refer to https://github.com/GoogleContainerTools/distroless for more details +FROM --platform=${TARGETPLATFORM:-linux/amd64} ${BASEIMAGE} +WORKDIR / +COPY --from=builder /workspace/azidgo . +# Kubernetes runAsNonRoot requires USER to be numeric +USER 65532:65532 + +ENTRYPOINT ["/azidgo"] diff --git a/examples/azure-identity/go/Makefile b/examples/azure-identity/go/Makefile new file mode 100644 index 0000000..ec7e6c6 --- /dev/null +++ b/examples/azure-identity/go/Makefile @@ -0,0 +1,64 @@ +REGISTRY ?= ghcr.io/azure/azure-workload-identity +IMAGE_NAME := azid-go +IMAGE_VERSION ?= latest + +DEMO_IMAGE := $(REGISTRY)/$(IMAGE_NAME):$(IMAGE_VERSION) + +## -------------------------------------- +## Images +## -------------------------------------- + +# Output type of docker buildx build +OUTPUT_TYPE ?= type=registry + +ALL_OS = linux windows +ALL_ARCH.linux = amd64 arm64 +ALL_ARCH.windows = amd64 +ALL_OSVERSIONS.windows := 1809 ltsc2022 +ALL_OS_ARCH.linux = $(foreach arch, ${ALL_ARCH.linux}, linux-$(arch)) +ALL_OS_ARCH.windows = $(foreach osver, ${ALL_OSVERSIONS.windows}, windows-$(osver)-$(foreach arch, ${ALL_ARCH.windows},$(arch))) +ALL_OS_ARCH = $(foreach os, $(ALL_OS), ${ALL_OS_ARCH.${os}}) + +# The architecture of the image +ARCH ?= amd64 +# OS Version for the Windows images: 1809, ltsc2022 +OSVERSION ?= 1809 + +.PHONY: container-linux +container-linux: + docker buildx build \ + --output=$(OUTPUT_TYPE) \ + --platform="linux/$(ARCH)" \ + --tag=$(DEMO_IMAGE)-linux-$(ARCH) . + +.PHONY: container-windows +container-windows: + docker buildx build \ + --build-arg OS_VERSION=$(OSVERSION) \ + --output=$(OUTPUT_TYPE) \ + --platform="windows/$(ARCH)" \ + --file=windows.Dockerfile \ + --tag=$(DEMO_IMAGE)-windows-$(OSVERSION)-$(ARCH) . + +.PHONY: container-all +container-all: + for arch in $(ALL_ARCH.linux); do \ + ARCH=$${arch} $(MAKE) container-linux; \ + done + for osversion in $(ALL_OSVERSIONS.windows); do \ + OSVERSION=$${osversion} $(MAKE) container-windows; \ + done + +.PHONY: push-manifest +push-manifest: + docker manifest create --amend $(DEMO_IMAGE) $(foreach osarch, $(ALL_OS_ARCH), $(DEMO_IMAGE)-${osarch}) + for arch in $(ALL_ARCH.linux); do docker manifest annotate --os linux --arch $${arch} $(DEMO_IMAGE) $(DEMO_IMAGE)-linux-$${arch}; done; \ + set -x; \ + for arch in $(ALL_ARCH.windows); do \ + for osversion in $(ALL_OSVERSIONS.windows); do \ + BASEIMAGE=mcr.microsoft.com/windows/nanoserver:$${osversion}; \ + full_version=`docker manifest inspect $${BASEIMAGE} | jq -r '.manifests[0].platform["os.version"]'`; \ + docker manifest annotate --os windows --arch $${arch} --os-version $${full_version} $(DEMO_IMAGE) $(DEMO_IMAGE)-windows-$${osversion}-$${arch}; \ + done; \ + done; \ + docker manifest push --purge $(DEMO_IMAGE) diff --git a/examples/azure-identity/go/go.mod b/examples/azure-identity/go/go.mod new file mode 100644 index 0000000..2e3d812 --- /dev/null +++ b/examples/azure-identity/go/go.mod @@ -0,0 +1,25 @@ +module github.com/Azure/azure-workload-identity/example/azure-identity/go + +go 1.19 + +require ( + github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0-beta.1 + github.com/Azure/azure-sdk-for-go/sdk/keyvault/azsecrets v0.11.0 + k8s.io/klog/v2 v2.80.1 +) + +require ( + github.com/Azure/azure-sdk-for-go/sdk/azcore v1.2.0 // indirect + github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.0 // indirect + github.com/Azure/azure-sdk-for-go/sdk/keyvault/internal v0.7.0 // indirect + github.com/AzureAD/microsoft-authentication-library-for-go v0.7.0 // indirect + github.com/go-logr/logr v1.2.0 // indirect + github.com/golang-jwt/jwt/v4 v4.4.2 // indirect + github.com/google/uuid v1.1.1 // indirect + github.com/kylelemons/godebug v1.1.0 // indirect + github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4 // indirect + golang.org/x/crypto v0.0.0-20220511200225-c6db032c6c88 // indirect + golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4 // indirect + golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e // indirect + golang.org/x/text v0.3.7 // indirect +) diff --git a/examples/azure-identity/go/go.sum b/examples/azure-identity/go/go.sum new file mode 100644 index 0000000..8e4be9a --- /dev/null +++ b/examples/azure-identity/go/go.sum @@ -0,0 +1,38 @@ +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.2.0 h1:sVW/AFBTGyJxDaMYlq0ct3jUXTtj12tQ6zE2GZUgVQw= +github.com/Azure/azure-sdk-for-go/sdk/azcore v1.2.0/go.mod h1:uGG2W01BaETf0Ozp+QxxKJdMBNRWPdstHG0Fmdwn1/U= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0-beta.1 h1:9qTV1dvmnXJ+2yBnNIm2SZZdXbSA+qlhksUq5Er9cTg= +github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.3.0-beta.1/go.mod h1:NBanQUfSWiWn3QEpWDTCU0IjBECKOYvl2R8xdRtMtiM= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.0 h1:jp0dGvZ7ZK0mgqnTSClMxa5xuRL7NZgHameVYF6BurY= +github.com/Azure/azure-sdk-for-go/sdk/internal v1.0.0/go.mod h1:eWRD7oawr1Mu1sLCawqVc0CUiF43ia3qQMxLscsKQ9w= +github.com/Azure/azure-sdk-for-go/sdk/keyvault/azsecrets v0.11.0 h1:82w8tzLcOwDP/Q35j/wEBPt0n0kVC3cjtPdD62G8UAk= +github.com/Azure/azure-sdk-for-go/sdk/keyvault/azsecrets v0.11.0/go.mod h1:S78i9yTr4o/nXlH76bKjGUye9Z2wSxO5Tz7GoDr4vfI= +github.com/Azure/azure-sdk-for-go/sdk/keyvault/internal v0.7.0 h1:Lg6BW0VPmCwcMlvOviL3ruHFO+H9tZNqscK0AeuFjGM= +github.com/Azure/azure-sdk-for-go/sdk/keyvault/internal v0.7.0/go.mod h1:9V2j0jn9jDEkCkv8w/bKTNppX/d0FVA1ud77xCIP4KA= +github.com/AzureAD/microsoft-authentication-library-for-go v0.7.0 h1:VgSJlZH5u0k2qxSpqyghcFQKmvYckj46uymKK5XzkBM= +github.com/AzureAD/microsoft-authentication-library-for-go v0.7.0/go.mod h1:BDJ5qMFKx9DugEg3+uQSDCdbYPr5s9vBTrL9P8TpqOU= +github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c= +github.com/dnaeon/go-vcr v1.1.0 h1:ReYa/UBrRyQdant9B4fNHGoCNKw6qh6P0fsdGmZpR7c= +github.com/go-logr/logr v1.2.0 h1:QK40JKJyMdUDz+h+xvCsru/bJhvG0UxvePV0ufL/AcE= +github.com/go-logr/logr v1.2.0/go.mod h1:jdQByPbusPIv2/zmleS9BjJVeZ6kBagPoEUsqbVz/1A= +github.com/golang-jwt/jwt/v4 v4.4.2 h1:rcc4lwaZgFMCZ5jxF9ABolDcIHdBytAFgqFPbSJQAYs= +github.com/golang-jwt/jwt/v4 v4.4.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= +github.com/google/uuid v1.1.1 h1:Gkbcsh/GbpXz7lPftLA3P6TYMwjCLYm83jiFQZF/3gY= +github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= +github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc= +github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw= +github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4 h1:Qj1ukM4GlMWXNdMBuXcXfz/Kw9s1qm0CLY32QxuSImI= +github.com/pkg/browser v0.0.0-20210115035449-ce105d075bb4/go.mod h1:N6UoU20jOqggOuDwUaBQpluzLNDqif3kq9z2wpdYEfQ= +github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= +github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= +golang.org/x/crypto v0.0.0-20220511200225-c6db032c6c88 h1:Tgea0cVUD0ivh5ADBX4WwuI12DUd2to3nCYe2eayMIw= +golang.org/x/crypto v0.0.0-20220511200225-c6db032c6c88/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= +golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4 h1:HVyaeDAYux4pnY+D/SiwmLOR36ewZ4iGQIIrtnuCjFA= +golang.org/x/net v0.0.0-20220425223048-2871e0cb64e4/go.mod h1:CfG3xpIq0wQ8r1q4Su4UZFWDARRcnwPjda9FqA0JpMk= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e h1:fLOSk5Q00efkSvAm+4xcoXD+RRmLmmulPn5I3Y9F2EM= +golang.org/x/sys v0.0.0-20211216021012-1d35b9e2eb4e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= +golang.org/x/text v0.3.7 h1:olpwvP2KacW1ZWvsR7uQhoyTYvKAupfQrRGBFM352Gk= +golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= +gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= +gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= +k8s.io/klog/v2 v2.80.1 h1:atnLQ121W371wYYFawwYx1aEY2eUfs4l3J72wtgAwV4= +k8s.io/klog/v2 v2.80.1/go.mod h1:y1WjHnz7Dj687irZUWR/WLkLc5N1YHtjLdmgWjndZn0= diff --git a/examples/azure-identity/go/main.go b/examples/azure-identity/go/main.go new file mode 100644 index 0000000..050683b --- /dev/null +++ b/examples/azure-identity/go/main.go @@ -0,0 +1,35 @@ +package main + +import ( + "context" + "os" + + "github.com/Azure/azure-sdk-for-go/sdk/azidentity" + "github.com/Azure/azure-sdk-for-go/sdk/keyvault/azsecrets" + "k8s.io/klog/v2" +) + +func main() { + keyvaultURL := os.Getenv("KEYVAULT_URL") + secretName := os.Getenv("SECRET_NAME") + + // create a secret client with the default credential + // DefaultAzureCredential will use the environment variables injected by the Azure Workload Identity + // mutating webhook to authenticate with Azure Key Vault. + + cred, err := azidentity.NewDefaultAzureCredential(nil) + if err != nil { + klog.Fatal(err) + } + client, err := azsecrets.NewClient(keyvaultURL, cred, nil) + if err != nil { + klog.Fatal(err) + } + + secretBundle, err := client.GetSecret(context.Background(), secretName, "", nil) + if err != nil { + klog.ErrorS(err, "failed to get secret from keyvault", "keyvault", keyvaultURL, "secretName", secretName) + os.Exit(1) + } + klog.InfoS("successfully got secret", "secret", *secretBundle.Value) +} diff --git a/examples/azure-identity/go/windows.Dockerfile b/examples/azure-identity/go/windows.Dockerfile new file mode 100644 index 0000000..96b151a --- /dev/null +++ b/examples/azure-identity/go/windows.Dockerfile @@ -0,0 +1,29 @@ +ARG BUILDER=mcr.microsoft.com/oss/go/microsoft/golang:1.19-bullseye +ARG SERVERCORE_CACHE=gcr.io/k8s-staging-e2e-test-images/windows-servercore-cache:1.0-linux-amd64-${OS_VERSION:-1809} +ARG BASEIMAGE=mcr.microsoft.com/windows/nanoserver:${OS_VERSION:-1809} + +FROM --platform=linux/amd64 ${BUILDER} as builder + +WORKDIR /workspace +# Copy the Go Modules manifests +COPY go.mod go.mod +COPY go.sum go.sum +# cache deps before building and copying source so that we don't need to re-download as much +# and so that source changes don't invalidate our downloaded layer +RUN go mod download + +# Copy the go source +COPY main.go main.go + +# Build +RUN CGO_ENABLED=0 GOOS=windows GO111MODULE=on go build -a -o azidgo.exe . + +FROM --platform=linux/amd64 ${SERVERCORE_CACHE} as core + +FROM --platform=${TARGETPLATFORM:-windows/amd64} ${BASEIMAGE} +WORKDIR / +COPY --from=builder /workspace/azidgo.exe . +COPY --from=core /Windows/System32/netapi32.dll /Windows/System32/netapi32.dll +USER ContainerAdministrator + +ENTRYPOINT [ "/azidgo.exe" ]