Skip to content

Commit

Permalink
Added a sample for CSP partners that demonstrates the secure app mode…
Browse files Browse the repository at this point in the history
…l. (#6)
  • Loading branch information
idwilliams committed Dec 3, 2018
1 parent 69132ce commit 12e853e
Show file tree
Hide file tree
Showing 10 changed files with 478 additions and 10 deletions.
Expand Up @@ -93,9 +93,11 @@ public IAggregatePartner getUserPartnerOperations()
System.out.println( "Authenticating user... " );
// give the partner SDK the new add token information
IAadLoginHandler loginHandler = new AadUserLoginHandler();
IPartnerCredentials userCredentials =
PartnerCredentials.getInstance().generateByUserCredentials( this.getConfiguration().getUserAuthentication().get( "ClientId" ),
loginHandler.authenticate(), loginHandler );

IPartnerCredentials userCredentials = PartnerCredentials.getInstance().generateByUserCredentials(
this.getConfiguration().getUserAuthentication().get( "ClientId" ),
loginHandler.authenticate(),
loginHandler );

System.out.println( "Authenticated!" );
this.userPartnerOperations = PartnerService.getInstance().createPartnerOperations( userCredentials );
Expand Down
1 change: 1 addition & 0 deletions secure-app-model/README.md
Expand Up @@ -17,6 +17,7 @@ To qualify as a CPV, you must on board to Microsoft Partner Center as a control

| Sample Name | Description |
|-------------|-------------|
| [CSP Sample](keyvault/cspsample/README.md) | Sample console application that demonstrates how a Cloud Solution Provider (CSP) partner can utilize the refresh token stored using the Partner Consent sample. |
| [Partner Consent](keyvault/partnerconsent/README.md) | Sample web application developed in Java, that demonstrates how a control panel vendor and Cloud Solution Provider partners can obtain the required consent. This process will store the refresh token for the authenticated user in an instance of Azure Key Vault.|

## Application identity and concepts
Expand Down
18 changes: 18 additions & 0 deletions secure-app-model/keyvault/cspsample/README.md
@@ -0,0 +1,18 @@
# Secure App Model

## Cloud Solution Provider (CSP) Sample

This sample demonstrates how a Cloud Solution Provider partner can utilize the refresh token obtained using the [Partner Consent](../partnerconsent/README.md) sample with the [Partner Center Java SDK](https://docs.microsoft.com/java/partnercenter/overview).

### Configuration

The following configurations in the [application.properties](src/main/resources/application.properties) file need to be modified:

* **keyvault.baseurl** - The base address for the instance of Azure Key Vault where the refresh token has been stored.
* **keyvault.clientId** - The identifier for the Azure AD application that has been allowed access to the instance of Azure Key Vault.
* **keyvault.clientSecret** - The application secret associated with the application configured to access the instance of Azure Key Vault.
* **partnercenter.accountId** - The account identifier, also known as the Azure AD tenant identifier, for the partner.
* **partnercenter.clientId** - The application identifier for the Azure AD application configured for use with the Partner Center API.
* **partnercenter.clientSecret** - The application secret associated with the application configured to access the Partner Center API.

Please note that in production scenarios we recommend that you use certificate based authentication to access the instance of Azure Key Vault. The [confidential client flow](https://github.com/AzureAD/azure-activedirectory-library-for-dotnet/wiki/Confidential-client-applications-flows) has been used in the sample for simplicity.
53 changes: 53 additions & 0 deletions secure-app-model/keyvault/cspsample/pom.xml
@@ -0,0 +1,53 @@
<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.microsoft.store.samples.secureappmodel</groupId>
<artifactId>cspsample</artifactId>
<version>1.0.0</version>
<packaging>jar</packaging>
<name>cspsample</name>
<url>http://maven.apache.org</url>
<properties>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
</properties>
<dependencies>
<dependency>
<groupId>com.microsoft.azure</groupId>
<artifactId>adal4j</artifactId>
<version>1.6.3</version>
</dependency>
<dependency>
<groupId>com.microsoft.azure</groupId>
<artifactId>azure-keyvault</artifactId>
<version>1.1.2</version>
</dependency>
<dependency>
<groupId>com.microsoft.rest</groupId>
<artifactId>client-runtime</artifactId>
<version>1.6.3</version>
</dependency>
<dependency>
<groupId>com.microsoft.store</groupId>
<artifactId>partnercenter</artifactId>
<version>1.8.1</version>
</dependency>
</dependencies>
<build>
<resources>
<resource>
<directory>src/main/resources</directory>
</resource>
</resources>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<version>3.8.0</version>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
@@ -0,0 +1,69 @@
// -----------------------------------------------------------------------
// <copyright file="Program.java" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// -----------------------------------------------------------------------

package com.microsoft.store.samples.secureappmodel.cspsample;

import java.util.Properties;

import com.microsoft.store.partnercenter.IAadLoginHandler;
import com.microsoft.store.partnercenter.IPartner;
import com.microsoft.store.partnercenter.IPartnerCredentials;
import com.microsoft.store.partnercenter.PartnerService;
import com.microsoft.store.partnercenter.extensions.PartnerCredentials;
import com.microsoft.store.partnercenter.models.partners.OrganizationProfile;
import com.microsoft.store.samples.secureappmodel.cspsample.security.SecureLoginHandler;

public class Program {
/**
* The name of the azure.properties resource file.
*/
private static final String AZURE_PROPERTIES = "application.properties";

/**
* The name of the partnercenter client identifier property.
*/
private static final String PARTNER_CENTER_CLIENT_ID = "partnercenter.clientId";

/**
* Entry point for the console application.
*
* @param args Arguments passed from the command line.
*/
public static void main(String args[])
{
IAadLoginHandler loginHandler;
IPartner partnerOperations;
IPartnerCredentials credentials;
OrganizationProfile profile;
Properties properties;

try
{
properties = new Properties();

// Load the properties using the azure.properties file found in the resources directory.
properties.load(Thread.currentThread().getContextClassLoader().getResourceAsStream(AZURE_PROPERTIES));

loginHandler = new SecureLoginHandler(properties);

credentials = PartnerCredentials.getInstance().generateByUserCredentials(
properties.getProperty(PARTNER_CENTER_CLIENT_ID),
loginHandler.authenticate(),
loginHandler);

partnerOperations = PartnerService.getInstance().createPartnerOperations(credentials);

profile = partnerOperations.getProfiles().getOrganizationProfile().get();

System.out.println(profile.getCompanyName());

}
catch(Exception ex)
{
ex.printStackTrace();
}
}
}
@@ -0,0 +1,21 @@
// -----------------------------------------------------------------------
// <copyright file="IVaultProvider.java" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// -----------------------------------------------------------------------

package com.microsoft.store.samples.secureappmodel.cspsample.security;

/**
* Represents a secure mechanism for retrieving and store sensitive information.
*/
public interface IVaultProvider
{
/**
* Gets the specified value from the vault.
*
* @param secretName Identifier of the value to be retrieved.
* @return The value for the specified secret.
*/
String getSecret(String secretName);
}
@@ -0,0 +1,154 @@
// -----------------------------------------------------------------------
// <copyright file="KeyVaultProvider.java" company="Microsoft">
// Copyright (c) Microsoft Corporation. All rights reserved.
// </copyright>
// -----------------------------------------------------------------------

package com.microsoft.store.samples.secureappmodel.cspsample.security;

import java.net.MalformedURLException;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

import com.microsoft.aad.adal4j.AuthenticationContext;
import com.microsoft.aad.adal4j.AuthenticationResult;
import com.microsoft.aad.adal4j.ClientCredential;
import com.microsoft.azure.keyvault.KeyVaultClient;
import com.microsoft.azure.keyvault.KeyVaultClientCustom;
import com.microsoft.azure.keyvault.authentication.KeyVaultCredentials;

/**
* Provides a secure mechanism for retrieving and store sensitive information using Azure Key Vault.
*/
public class KeyVaultProvider implements IVaultProvider
{
/**
* The client used to interact with the Azure Key Vault service.
*/
private KeyVaultClientCustom client;

/**
* The vault name, e.g. https://myvault.vault.azure.net
*/
private String vaultBaseUrl;

/**
* Initializes a new instance of the {@link KeyVaultProvider} class.
*
* @param vaultBaseUrl The vault name, e.g. https://myvault.vault.azure.net
* @param clientId The identifier of the client requesting the token.
* @param clientSecret The secure secret of the client requesting the token.
*/
public KeyVaultProvider(String vaultBaseUrl, String clientId, String clientSecret)
{
client = getKeyVaultClient(clientId, clientSecret);
this.vaultBaseUrl = vaultBaseUrl;
}

/**
* Gets the specified value from the vault.
*
* @param secretName Identifier of the value to be retrieved.
* @return The value for the specified secret.
*/
public String getSecret(String secretName)
{
return client.getSecret(vaultBaseUrl, secretName).value();
}

/**
* Stores the specified value in the vault.
*
* @param secretName Identifier of the value to be stored.
* @param value The value to be stored.
*/
public void setSecret(String secretName, String value)
{
client.setSecret(vaultBaseUrl, secretName, value);
}

/**
* Gets an access token from the authority.
*
* @param authorization Address of the authority to issue the token.
* @param resource Identifier of the target resource that is the recipient of the requested token.
* @param clientId The identifier of the client requesting the token.
* @param clientSecret The secure secret of the client requesting the token.
* @return An instance of {@link AuthenticationResult} that contians an access token and refresh token.
*
* @throws ExecutionException {@link ExecutionException}
* @throws InterruptedException {@link InterruptedException}
* @throws MalformedURLException {@link MalformedURLException}
*/
private AuthenticationResult getAccessToken(String authorization, String resource, String clientId, String clientSecret)
throws ExecutionException, InterruptedException, MalformedURLException
{
AuthenticationContext authContext;
AuthenticationResult authResult;
ExecutorService service = null;
Future<AuthenticationResult> future;

try
{
service = Executors.newFixedThreadPool(1);
authContext = new AuthenticationContext(authorization, true, service);

future = authContext.acquireToken(
resource,
new ClientCredential(
clientId,
clientSecret),
null);

authResult = future.get();

return authResult;
}
finally
{
service.shutdown();
}
}

/**
* Gets a client that is capable of interacting with the Azure Key Vault service.
*
* @param clientId The identifier of the client requesting the token.
* @param clientSecret The secure secret of the client requesting the token.
*
* @return A client that is capable of interacting with the Azure Key Vault service.
*/
private KeyVaultClientCustom getKeyVaultClient(String clientId, String clientSecret)
{
return new KeyVaultClient(new KeyVaultCredentials()
{
/**
* @param authorization Address of the authority to issue the token.
* @param resource Identifier of the target resource that is the recipient of the requested token, a URL.
* @param scope The scope of the authentication request.
*
* @return Access token to be used with Azure Key Vault operations.
*/
@Override
public String doAuthenticate(String authorization, String resource, String scope)
{
AuthenticationResult authResult;

try
{
authResult = getAccessToken(authorization, resource, clientId, clientSecret);

return authResult.getAccessToken();
}
catch(Exception ex)
{
ex.printStackTrace();
}

return "";
}
});
}
}

0 comments on commit 12e853e

Please sign in to comment.