Skip to content

Commit

Permalink
feat: add msal-java example (#375)
Browse files Browse the repository at this point in the history
  • Loading branch information
Ernest Wong committed Feb 17, 2022
1 parent 306abde commit 2618ac4
Show file tree
Hide file tree
Showing 11 changed files with 240 additions and 11 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/publish-images.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ jobs:
strategy:
fail-fast: false
matrix:
dir: [examples/msal-go, examples/msal-net/akvdotnet, examples/msal-node, examples/msal-python]
dir: [examples/msal-go, examples/msal-net/akvdotnet, examples/msal-node, examples/msal-python, examples/msal-java]
runs-on: ubuntu-20.04
steps:
- uses: actions/checkout@v2
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -34,3 +34,6 @@ _artifacts/

# Makefile output
.image-*

# java target from msal-java example
target/
4 changes: 3 additions & 1 deletion docs/book/src/quick-start.md
Original file line number Diff line number Diff line change
Expand Up @@ -235,7 +235,7 @@ metadata:
spec:
serviceAccountName: ${SERVICE_ACCOUNT_NAME}
containers:
- image: ghcr.io/azure/azure-workload-identity/msal-go:latest
- image: ghcr.io/azure/azure-workload-identity/msal-go
name: oidc
env:
- name: KEYVAULT_NAME
Expand All @@ -247,6 +247,8 @@ spec:
EOF
```

> Feel free to swap the msal-go example image above with a list of [language-specific examples](./topics/language-specific-examples/msal.md) we provide.
To check whether all properties are injected properly by the webhook:

```bash
Expand Down
14 changes: 7 additions & 7 deletions docs/book/src/topics/language-specific-examples/msal.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
# Microsoft Authentication Library (MSAL)

| Language | Library | Image | Example | Has Windows Images |
| --------------------- | --------------------------------------------------------------------------------------------------------------------- | ---------------------------------------------------------- | ---------------------------------------------------------------------------------------------------- | ------------------ |
| Go | [microsoft-authentication-library-for-go](https://github.com/AzureAD/microsoft-authentication-library-for-go) | `ghcr.io/azure/azure-workload-identity/msal-go:latest` | [Link](https://github.com/Azure/azure-workload-identity/tree/main/examples/msal-go) ||
| C# | [microsoft-authentication-library-for-dotnet](https://github.com/AzureAD/microsoft-authentication-library-for-dotnet) | `ghcr.io/azure/azure-workload-identity/msal-net:latest` | [Link](https://github.com/Azure/azure-workload-identity/tree/main/examples/msal-net/akvdotnet) ||
| JavaScript/TypeScript | [microsoft-authentication-library-for-js](https://github.com/AzureAD/microsoft-authentication-library-for-js) | `ghcr.io/azure/azure-workload-identity/msal-node:latest` | [Link](https://github.com/Azure/azure-workload-identity/tree/main/examples/msal-node) ||
| Python | [microsoft-authentication-library-for-python](https://github.com/AzureAD/microsoft-authentication-library-for-python) | `ghcr.io/azure/azure-workload-identity/msal-python:latest` | [Link](https://github.com/Azure/azure-workload-identity/tree/main/examples/msal-python) ||
| Java | [microsoft-authentication-library-for-java](https://github.com/AzureAD/microsoft-authentication-library-for-java) | N/A | N/A ([known issue](https://github.com/AzureAD/microsoft-authentication-library-for-java/issues/437)) ||
| Language | Library | Image | Example | Has Windows Images |
| --------------------- | --------------------------------------------------------------------------------------------------------------------- | --------------------------------------------------- | ---------------------------------------------------------------------------------------------- | ------------------ |
| C# | [microsoft-authentication-library-for-dotnet](https://github.com/AzureAD/microsoft-authentication-library-for-dotnet) | `ghcr.io/azure/azure-workload-identity/msal-net` | [Link](https://github.com/Azure/azure-workload-identity/tree/main/examples/msal-net/akvdotnet) ||
| Go | [microsoft-authentication-library-for-go](https://github.com/AzureAD/microsoft-authentication-library-for-go) | `ghcr.io/azure/azure-workload-identity/msal-go` | [Link](https://github.com/Azure/azure-workload-identity/tree/main/examples/msal-go) ||
| Java | [microsoft-authentication-library-for-java](https://github.com/AzureAD/microsoft-authentication-library-for-java) | `ghcr.io/azure/azure-workload-identity/msal-java` | [Link](https://github.com/Azure/azure-workload-identity/tree/main/examples/msal-java) ||
| JavaScript/TypeScript | [microsoft-authentication-library-for-js](https://github.com/AzureAD/microsoft-authentication-library-for-js) | `ghcr.io/azure/azure-workload-identity/msal-node` | [Link](https://github.com/Azure/azure-workload-identity/tree/main/examples/msal-node) ||
| Python | [microsoft-authentication-library-for-python](https://github.com/AzureAD/microsoft-authentication-library-for-python) | `ghcr.io/azure/azure-workload-identity/msal-python` | [Link](https://github.com/Azure/azure-workload-identity/tree/main/examples/msal-python) ||
12 changes: 12 additions & 0 deletions examples/msal-java/Dockerfile
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
FROM maven:3.8.4-jdk-11 as builder
WORKDIR /app
COPY pom.xml .
RUN mvn -e -B dependency:resolve
COPY src ./src
RUN mvn -e -B package

FROM gcr.io/distroless/java:11-nonroot
COPY --from=builder /app/target/msal-java-*.jar /app.jar
# Kubernetes runAsNonRoot requires USER to be numeric
USER 65532:65532
CMD ["/app.jar"]
39 changes: 39 additions & 0 deletions examples/msal-java/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
REGISTRY ?= ghcr.io/azure/azure-workload-identity
IMAGE_NAME := msal-java
IMAGE_VERSION ?= latest

DEMO_IMAGE := $(REGISTRY)/$(IMAGE_NAME):$(IMAGE_VERSION)

## --------------------------------------
## Images
## --------------------------------------

# Output type of docker buildx build
OUTPUT_TYPE ?= type=registry

ALL_OS = linux
ALL_ARCH.linux = amd64 arm64
ALL_OS_ARCH.linux = $(foreach arch, ${ALL_ARCH.linux}, linux-$(arch))
ALL_OS_ARCH = $(foreach os, $(ALL_OS), ${ALL_OS_ARCH.${os}})

# The architecture of the image
ARCH ?= amd64

.PHONY: container-linux
container-linux:
docker buildx build \
--output=$(OUTPUT_TYPE) \
--platform="linux/$(ARCH)" \
--tag=$(DEMO_IMAGE)-linux-$(ARCH) .

.PHONY: container-all
container-all:
for arch in $(ALL_ARCH.linux); do \
ARCH=$${arch} $(MAKE) container-linux; \
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; \
docker manifest push --purge $(DEMO_IMAGE)
96 changes: 96 additions & 0 deletions examples/msal-java/pom.xml
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
<?xml version="1.0" encoding="UTF-8"?>

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>

<groupId>com.example.msal.java</groupId>
<artifactId>msal-java</artifactId>
<version>1.0-SNAPSHOT</version>

<name>msal-java</name>
<!-- FIXME change it to the project's website -->
<url>http://www.example.com</url>

<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
</properties>

<dependencies>
<dependency>
<groupId>com.azure</groupId>
<artifactId>azure-security-keyvault-secrets</artifactId>
<version>4.2.3</version>
</dependency>
<dependency>
<groupId>com.azure</groupId>
<artifactId>azure-identity</artifactId>
<version>1.2.0</version>
</dependency>
<dependency>
<groupId>com.azure</groupId>
<artifactId>azure-core</artifactId>
<version>1.25.0</version>
</dependency>
<dependency>
<groupId>com.microsoft.azure</groupId>
<artifactId>msal4j</artifactId>
<version>1.11.2</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.4</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>com.example.msal.java.App</mainClass>
</transformer>
</transformers>
<filters>
<filter>
<artifact>*:*</artifact>
<excludes>
<exclude>META-INF/*.SF</exclude>
<exclude>META-INF/*.DSA</exclude>
<exclude>META-INF/*.RSA</exclude>
</excludes>
</filter>
</filters>
</configuration>
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-dependency-plugin</artifactId>
<version>2.6</version>
<executions>
<execution>
<id>unpack-dependencies</id>
<phase>package</phase>
<goals>
<goal>unpack-dependencies</goal>
</goals>
<configuration>
<excludeScope>system</excludeScope>
<excludes>META-INF/*.SF,META-INF/*.DSA,META-INF/*.RSA</excludes>
<excludeGroupIds>junit,org.mockito,org.hamcrest</excludeGroupIds>
<outputDirectory>${project.build.directory}/classes</outputDirectory>
</configuration>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
22 changes: 22 additions & 0 deletions examples/msal-java/src/main/java/com/example/msal/java/App.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
package com.example.msal.java;

import java.util.Map;

import com.azure.security.keyvault.secrets.SecretClient;
import com.azure.security.keyvault.secrets.SecretClientBuilder;
import com.azure.security.keyvault.secrets.models.KeyVaultSecret;

public class App {
public static void main(String[] args) {
Map<String, String> env = System.getenv();
String keyvaultName = env.get("KEYVAULT_NAME");
String secretName = env.get("SECRET_NAME");

SecretClient secretClient = new SecretClientBuilder()
.vaultUrl(String.format("https://%s.vault.azure.net", keyvaultName))
.credential(new CustomTokenCredential())
.buildClient();
KeyVaultSecret secret = secretClient.getSecret(secretName);
System.out.printf("successfully got secret, secret=%s", secret.getValue());
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
package com.example.msal.java;

import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.time.ZoneOffset;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import com.azure.core.credential.AccessToken;
import com.azure.core.credential.TokenCredential;
import com.azure.core.credential.TokenRequestContext;
import com.microsoft.aad.msal4j.ClientCredentialFactory;
import com.microsoft.aad.msal4j.ClientCredentialParameters;
import com.microsoft.aad.msal4j.ConfidentialClientApplication;
import com.microsoft.aad.msal4j.IAuthenticationResult;
import com.microsoft.aad.msal4j.IClientCredential;

import reactor.core.publisher.Mono;

public class CustomTokenCredential implements TokenCredential {
public Mono<AccessToken> getToken(TokenRequestContext request) {
Map<String, String> env = System.getenv();
String clientAssertion;
try {
clientAssertion = new String(Files.readAllBytes(Paths.get(env.get("AZURE_FEDERATED_TOKEN_FILE"))),
StandardCharsets.UTF_8);
} catch (IOException e) {
throw new RuntimeException(e);
}

IClientCredential credential = ClientCredentialFactory.createFromClientAssertion(clientAssertion);
String authority = env.get("AZURE_AUTHORITY_HOST") + env.get("AZURE_TENANT_ID");
try {
ConfidentialClientApplication app = ConfidentialClientApplication
.builder(env.get("AZURE_CLIENT_ID"), credential).authority(authority).build();

Set<String> scopes = new HashSet<>();
for (String scope : request.getScopes())
scopes.add(scope);

ClientCredentialParameters parameters = ClientCredentialParameters.builder(scopes).build();
IAuthenticationResult result = app.acquireToken(parameters).join();
return Mono.just(
new AccessToken(result.accessToken(), result.expiresOnDate().toInstant().atOffset(ZoneOffset.UTC)));
} catch (Exception e) {
System.out.printf("Error creating client application: %s", e.getMessage());
System.exit(1);
}

return Mono.empty();
}
}
2 changes: 1 addition & 1 deletion examples/msal-node/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ ADD . /app
WORKDIR /app
RUN npm install

FROM gcr.io/distroless/nodejs:14
FROM gcr.io/distroless/nodejs:16
COPY --from=build-env /app /app
WORKDIR /app
# Kubernetes runAsNonRoot requires USER to be numeric
Expand Down
2 changes: 1 addition & 1 deletion examples/msal-python/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ COPY requirements.txt /requirements.txt
RUN /venv/bin/pip install --disable-pip-version-check -r /requirements.txt

# Copy the virtualenv into a distroless image
FROM gcr.io/distroless/python3-debian10
FROM gcr.io/distroless/python3-debian11
COPY --from=build-venv /venv /venv
COPY . /app
WORKDIR /app
Expand Down

0 comments on commit 2618ac4

Please sign in to comment.