diff --git a/services/azure-media/pom.xml b/services/azure-media/pom.xml index 746c52f29b9b..20dfdefd1ddd 100644 --- a/services/azure-media/pom.xml +++ b/services/azure-media/pom.xml @@ -62,7 +62,12 @@ ${project.groupId} azure-core ${project.version} - + + + com.microsoft.azure + adal4j + 1.2.0 + org.apache.httpcomponents httpclient diff --git a/services/azure-media/src/main/java/com/microsoft/windowsazure/services/media/Exports.java b/services/azure-media/src/main/java/com/microsoft/windowsazure/services/media/Exports.java index debddb291e4e..38c00dfbb8a4 100644 --- a/services/azure-media/src/main/java/com/microsoft/windowsazure/services/media/Exports.java +++ b/services/azure-media/src/main/java/com/microsoft/windowsazure/services/media/Exports.java @@ -21,14 +21,12 @@ import com.microsoft.windowsazure.core.Builder; import com.microsoft.windowsazure.core.UserAgentFilter; +import com.microsoft.windowsazure.services.media.authentication.AzureAdTokenFactory; import com.microsoft.windowsazure.services.media.implementation.BatchMimeMultipartBodyWritter; import com.microsoft.windowsazure.services.media.implementation.MediaContentProvider; import com.microsoft.windowsazure.services.media.implementation.MediaExceptionProcessor; import com.microsoft.windowsazure.services.media.implementation.MediaRestProxy; -import com.microsoft.windowsazure.services.media.implementation.OAuthContract; import com.microsoft.windowsazure.services.media.implementation.OAuthFilter; -import com.microsoft.windowsazure.services.media.implementation.OAuthRestProxy; -import com.microsoft.windowsazure.services.media.implementation.OAuthTokenManager; import com.microsoft.windowsazure.services.media.implementation.ODataEntityCollectionProvider; import com.microsoft.windowsazure.services.media.implementation.ODataEntityProvider; import com.microsoft.windowsazure.services.media.implementation.RedirectFilter; @@ -44,10 +42,9 @@ public class Exports implements Builder.Exports { */ @Override public void register(Builder.Registry registry) { + registry.add(new AzureAdTokenFactory()); registry.add(MediaContract.class, MediaExceptionProcessor.class); registry.add(MediaRestProxy.class); - registry.add(OAuthContract.class, OAuthRestProxy.class); - registry.add(OAuthTokenManager.class); registry.add(OAuthFilter.class); registry.add(ResourceLocationManager.class); registry.add(RedirectFilter.class); diff --git a/services/azure-media/src/main/java/com/microsoft/windowsazure/services/media/MediaConfiguration.java b/services/azure-media/src/main/java/com/microsoft/windowsazure/services/media/MediaConfiguration.java index 8d4eaed05d71..c58423062c79 100644 --- a/services/azure-media/src/main/java/com/microsoft/windowsazure/services/media/MediaConfiguration.java +++ b/services/azure-media/src/main/java/com/microsoft/windowsazure/services/media/MediaConfiguration.java @@ -1,11 +1,11 @@ /** * Copyright Microsoft Corporation - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -14,11 +14,14 @@ */ package com.microsoft.windowsazure.services.media; +import java.net.URI; + import com.microsoft.windowsazure.Configuration; +import com.microsoft.windowsazure.services.media.authentication.TokenProvider; /** * Provides functionality to create a media services configuration. - * + * */ public final class MediaConfiguration { @@ -26,152 +29,42 @@ private MediaConfiguration() { } /** - * Defines the media service configuration URI constant. - * - */ - public static final String URI = "media.uri"; - - /** - * Defines the OAUTH configuration URI constant. - * - */ - public static final String OAUTH_URI = "media.oauth.uri"; - - /** - * Defines the OAUTH configuration client ID constant. - * + * The token provider object */ - public static final String OAUTH_CLIENT_ID = "media.oauth.client.id"; + public static final String AZURE_AD_TOKEN_PROVIDER = "media.azuread.tokenprovider"; /** - * Defines the OAUTH configuration client secret constant. - * + * The azure media services account uri */ - public static final String OAUTH_CLIENT_SECRET = "media.oauth.client.secret"; + public static final String AZURE_AD_API_SERVER = "media.azuread.account_api_uri"; /** - * Defines the SCOPE of the media service sent to OAUTH. + * Returns the default Configuration provisioned for the specified AMS account and token provider. + * @param apiServer the AMS account uri + * @param azureAdTokenProvider the token provider + * @return a Configuration */ - public static final String OAUTH_SCOPE = "media.oauth.scope"; + public static Configuration configureWithAzureAdTokenProvider( + URI apiServer, + TokenProvider azureAdTokenProvider) { - /** - * Creates a media service configuration using the specified media service - * base URI, OAUTH URI, client ID, and client secret. - * - * @param mediaServiceUri - * A String object that represents the media service - * URI. - * - * @param oAuthUri - * A String object that represents the OAUTH URI. - * - * @param clientId - * A String object that represents the client ID. - * - * @param clientSecret - * A String object that represents the client - * secret. - * - * @param scope - * A String object that represents the scope. - * - * @return A Configuration object that can be used when - * creating an instance of the MediaService class. - * - */ - public static Configuration configureWithOAuthAuthentication( - String mediaServiceUri, String oAuthUri, String clientId, - String clientSecret, String scope) { - return configureWithOAuthAuthentication(null, - Configuration.getInstance(), mediaServiceUri, oAuthUri, - clientId, clientSecret, scope); + return configureWithAzureAdTokenProvider(Configuration.getInstance(), apiServer, azureAdTokenProvider); } /** - * Creates a media service configuration using the specified configuration, - * media service base URI, OAuth URI, client ID, and client secret. - * - * @param configuration - * A previously instantiated Configuration object. - * - * @param mediaServiceUri - * A String object that represents the URI of media - * service. - * - * @param oAuthUri - * A String object that represents the URI of OAuth - * service. - * - * @param clientId - * A String object that represents the client ID. - * - * @param clientSecret - * A String object that represents the client - * secret. - * - * @param scope - * A String object that represents the scope. - * - * @return A Configuration object that can be used when - * creating an instance of the MediaService class. - * + * Setup a Configuration with specified Configuration, AMS account and token provider + * @param configuration The target configuration + * @param apiServer the AMS account uri + * @param azureAdTokenProvider the token provider + * @return the target Configuration */ - public static Configuration configureWithOAuthAuthentication( - Configuration configuration, String mediaServiceUri, - String oAuthUri, String clientId, String clientSecret, String scope) { - return configureWithOAuthAuthentication(null, configuration, - mediaServiceUri, oAuthUri, clientId, clientSecret, scope); - } - - /** - * Creates a media service configuration using the specified profile, - * configuration, media service base URI, OAuth URI, client ID, and client - * secret. - * - * @param profile - * A String object that represents the profile. - * - * @param configuration - * A previously instantiated Configuration object. - * - * @param mediaServiceUri - * A String object that represents the URI of media - * service. - * - * @param oAuthUri - * A String object that represents the URI of OAUTH - * service. - * - * @param clientId - * A String object that represents the client ID. - * - * @param clientSecret - * A String object that represents the client - * secret. - * - * @param scope - * A String object that represents the scope. - * - * @return A Configuration object that can be used when - * creating an instance of the MediaService class. - * - */ - public static Configuration configureWithOAuthAuthentication( - String profile, Configuration configuration, - String mediaServiceUri, String oAuthUri, String clientId, - String clientSecret, String scope) { - - if (profile == null) { - profile = ""; - } else if (profile.length() != 0 && !profile.endsWith(".")) { - profile = profile + "."; - } + public static Configuration configureWithAzureAdTokenProvider( + Configuration configuration, + URI apiServer, + TokenProvider azureAdTokenProvider) { - configuration.setProperty(profile + URI, mediaServiceUri); - configuration.setProperty(profile + OAUTH_URI, oAuthUri); - configuration.setProperty(profile + OAUTH_CLIENT_ID, clientId); - configuration.setProperty(profile + OAUTH_CLIENT_SECRET, clientSecret); - configuration.setProperty(profile + OAUTH_SCOPE, scope); + configuration.setProperty(AZURE_AD_API_SERVER, apiServer.toString()); + configuration.setProperty(AZURE_AD_TOKEN_PROVIDER, azureAdTokenProvider); return configuration; } diff --git a/services/azure-media/src/main/java/com/microsoft/windowsazure/services/media/MediaService.java b/services/azure-media/src/main/java/com/microsoft/windowsazure/services/media/MediaService.java index df95d2d602c1..c7a8e9c77e2e 100644 --- a/services/azure-media/src/main/java/com/microsoft/windowsazure/services/media/MediaService.java +++ b/services/azure-media/src/main/java/com/microsoft/windowsazure/services/media/MediaService.java @@ -40,7 +40,7 @@ public static MediaContract create() { * * @param config * A Configuration object that represents the - * configuration for the service bus service. + * configuration for the media service account. * */ public static MediaContract create(Configuration config) { @@ -61,7 +61,7 @@ public static MediaContract create(String profile) { * * @param config * A Configuration object that represents the - * configuration for the service bus service. + * configuration for the media service account. * */ public static MediaContract create(String profile, Configuration config) { diff --git a/services/azure-media/src/main/java/com/microsoft/windowsazure/services/media/authentication/AzureAdAccessToken.java b/services/azure-media/src/main/java/com/microsoft/windowsazure/services/media/authentication/AzureAdAccessToken.java new file mode 100644 index 000000000000..b13d3daecf72 --- /dev/null +++ b/services/azure-media/src/main/java/com/microsoft/windowsazure/services/media/authentication/AzureAdAccessToken.java @@ -0,0 +1,48 @@ +package com.microsoft.windowsazure.services.media.authentication; + +import java.util.Date; + +/** + * Represents an access token + */ +public class AzureAdAccessToken { + + private final String accessToken; + + private final Date expiresOn; + + /** + * Gets the access token + * @return the access token + */ + public String getAccessToken() { + return this.accessToken; + } + + /** + * Gets the expiration date + * @return the expiration date + */ + public Date getExpiresOnDate() { + return this.expiresOn; + } + + /** + * Instantiate a representation of an access token + * @param accessToken the access token + * @param expiresOn the expiration date + */ + public AzureAdAccessToken(String accessToken, Date expiresOn) { + + if (accessToken == null || accessToken.trim().isEmpty()) { + throw new IllegalArgumentException("accessToken"); + } + + if (expiresOn == null) { + throw new NullPointerException("expiresOn"); + } + + this.accessToken = accessToken; + this.expiresOn = expiresOn; + } +} diff --git a/services/azure-media/src/main/java/com/microsoft/windowsazure/services/media/authentication/AzureAdClientSymmetricKey.java b/services/azure-media/src/main/java/com/microsoft/windowsazure/services/media/authentication/AzureAdClientSymmetricKey.java new file mode 100644 index 000000000000..ad0e0aa143d2 --- /dev/null +++ b/services/azure-media/src/main/java/com/microsoft/windowsazure/services/media/authentication/AzureAdClientSymmetricKey.java @@ -0,0 +1,44 @@ +package com.microsoft.windowsazure.services.media.authentication; + +/** + * Represents a symmetric key pair of ClientId & ClientKey + */ +public class AzureAdClientSymmetricKey { + + private final String clientId; + private final String clientKey; + + /** + * Gets the client ID. + * @return the client ID. + */ + public String getClientId() { + return this.clientId; + } + + /** + * Gets the client key. + * @return the client key. + */ + public String getClientKey() { + return this.clientKey; + } + + /** + * Initializes a new instance of the AzureAdClientSymmetricKey class. + * @param clientId The client ID. + * @param clientKey The client key. + */ + public AzureAdClientSymmetricKey(String clientId, String clientKey) { + if (clientId == null || clientId.trim().isEmpty()) { + throw new IllegalArgumentException("clientId"); + } + + if (clientKey == null || clientKey.trim().isEmpty()) { + throw new IllegalArgumentException("clientKey"); + } + + this.clientId = clientId; + this.clientKey = clientKey; + } +} diff --git a/services/azure-media/src/main/java/com/microsoft/windowsazure/services/media/authentication/AzureAdClientUsernamePassword.java b/services/azure-media/src/main/java/com/microsoft/windowsazure/services/media/authentication/AzureAdClientUsernamePassword.java new file mode 100644 index 000000000000..c9d51cbce115 --- /dev/null +++ b/services/azure-media/src/main/java/com/microsoft/windowsazure/services/media/authentication/AzureAdClientUsernamePassword.java @@ -0,0 +1,44 @@ +package com.microsoft.windowsazure.services.media.authentication; + +/** + * Represents a pair of username & password credentials + */ +public class AzureAdClientUsernamePassword { + + private final String username; + private final String password; + + /** + * Gets the username. + * @return the username. + */ + public String getUsername() { + return this.username; + } + + /** + * Gets the password. + * @return the password. + */ + public String getPassword() { + return this.password; + } + + /** + * Initializes a new instance of the AzureAdClientSymmetricKey class. + * @param clientId The client ID. + * @param clientKey The client key. + */ + public AzureAdClientUsernamePassword(String username, String password) { + if (username == null || username.trim().isEmpty()) { + throw new IllegalArgumentException("username"); + } + + if (password == null || password.trim().isEmpty()) { + throw new IllegalArgumentException("password"); + } + + this.username = username; + this.password = password; + } +} diff --git a/services/azure-media/src/main/java/com/microsoft/windowsazure/services/media/authentication/AzureAdTokenCredentialType.java b/services/azure-media/src/main/java/com/microsoft/windowsazure/services/media/authentication/AzureAdTokenCredentialType.java new file mode 100644 index 000000000000..b83277a64981 --- /dev/null +++ b/services/azure-media/src/main/java/com/microsoft/windowsazure/services/media/authentication/AzureAdTokenCredentialType.java @@ -0,0 +1,28 @@ +package com.microsoft.windowsazure.services.media.authentication; + +/** + * Enumerates the different types of credentials available + * + */ +public enum AzureAdTokenCredentialType { + + /** + * User Credential by prompting user for user name and password. + */ + UserCredential, + + /** + * User Secret Credential by providing user name and password via configuration. + */ + UserSecretCredential, + + /** + * Service Principal with the symmetric key credential. + */ + ServicePrincipalWithClientSymmetricKey, + + /** + * Service Principal with the certificate credential. + */ + ServicePrincipalWithClientCertificate +} diff --git a/services/azure-media/src/main/java/com/microsoft/windowsazure/services/media/authentication/AzureAdTokenCredentials.java b/services/azure-media/src/main/java/com/microsoft/windowsazure/services/media/authentication/AzureAdTokenCredentials.java new file mode 100644 index 000000000000..e64ffc4465ae --- /dev/null +++ b/services/azure-media/src/main/java/com/microsoft/windowsazure/services/media/authentication/AzureAdTokenCredentials.java @@ -0,0 +1,160 @@ +package com.microsoft.windowsazure.services.media.authentication; + +import com.microsoft.aad.adal4j.AsymmetricKeyCredential; +import com.microsoft.aad.adal4j.ClientCredential; + +/** + * Represents an Azure AD Credential for a specific resource + */ +public class AzureAdTokenCredentials { + + private String tenant; + + private ClientCredential clientKey; + + private AsymmetricKeyCredential asymmetricKeyCredential; + + private AzureAdClientUsernamePassword azureAdClientUsernamePassword; + + private AzureAdTokenCredentialType credentialType; + + private AzureEnvironment azureEnvironment; + + /** + * Gets the tenant. + * @return the tenant. + */ + public String getTenant() { + return this.tenant; + } + + /** + * Gets the client username password + * @return the client symmetric key. + */ + public AzureAdClientUsernamePassword getAzureAdClientUsernamePassword() { + return this.azureAdClientUsernamePassword; + } + + /** + * Gets the client symmetric key credential. + * @return the ClientCredential + */ + public ClientCredential getClientKey() { + return this.clientKey; + } + + /** + * Gets the AsymmetricKeyCredential + * @return the AsymmetricKeyCredential + */ + public AsymmetricKeyCredential getAsymmetricKeyCredential() { + return this.asymmetricKeyCredential; + } + + /** + * Gets the credential type. + * @return the credential type. + */ + public AzureAdTokenCredentialType getCredentialType() { + return this.credentialType; + } + + /** + * Gets the environment. + * @return the environment. + */ + public AzureEnvironment getAzureEnvironment() { + return this.azureEnvironment; + } + + /** + * Initializes a new instance of the AzureAdTokenCredentials class. + * @param tenant The tenant + * @param azureAdClientUsernamePassword the user credentials + * @param azureEnvironment The environment + */ + public AzureAdTokenCredentials(String tenant, AzureAdClientUsernamePassword azureAdClientUsernamePassword, AzureEnvironment azureEnvironment) { + if (tenant == null || tenant.trim().isEmpty()) { + throw new IllegalArgumentException("tenant"); + } + + if (azureAdClientUsernamePassword == null) { + throw new NullPointerException("azureAdClientUsernamePassword"); + } + + if (azureEnvironment == null) { + throw new NullPointerException("azureEnvironment"); + } + + this.tenant = tenant; + this.azureAdClientUsernamePassword = azureAdClientUsernamePassword; + this.azureEnvironment = azureEnvironment; + this.credentialType = AzureAdTokenCredentialType.UserSecretCredential; + } + + /** + * Initializes a new instance of the AzureAdTokenCredentials class. + * @param tenant The tenant + * @param azureEnvironment The environment + */ + public AzureAdTokenCredentials(String tenant, AzureEnvironment azureEnvironment) { + if (tenant == null || tenant.trim().isEmpty()) { + throw new IllegalArgumentException("tenant"); + } + + if (azureEnvironment == null) { + throw new NullPointerException("azureEnvironment"); + } + + this.tenant = tenant; + this.azureEnvironment = azureEnvironment; + this.credentialType = AzureAdTokenCredentialType.UserSecretCredential; + } + + /** + * Initializes a new instance of the AzureAdTokenCredentials class. + * @param tenant The tenant + * @param azureAdClientSymmetricKey an instance of AzureAdClientSymmetricKey + * @param azureEnvironment The environment + */ + public AzureAdTokenCredentials(String tenant, AzureAdClientSymmetricKey azureAdClientSymmetricKey, AzureEnvironment azureEnvironment) { + if (tenant == null || tenant.trim().isEmpty()) { + throw new IllegalArgumentException("tenant"); + } + + if (azureAdClientSymmetricKey == null) { + throw new NullPointerException("azureAdClientSymmetricKey"); + } + + if (azureEnvironment == null) { + throw new NullPointerException("azureEnvironment"); + } + + this.tenant = tenant; + this.azureEnvironment = azureEnvironment; + this.clientKey = new ClientCredential(azureAdClientSymmetricKey.getClientId(), azureAdClientSymmetricKey.getClientKey()); + this.credentialType = AzureAdTokenCredentialType.ServicePrincipalWithClientSymmetricKey; + } + + + public AzureAdTokenCredentials(String tenant, AsymmetricKeyCredential asymmetricKeyCredential, AzureEnvironment azureEnvironment) { + if (tenant == null || tenant.trim().isEmpty()) { + throw new IllegalArgumentException("tenant"); + } + + if (asymmetricKeyCredential == null) { + throw new NullPointerException("asymmetricKeyCredential"); + } + + if (azureEnvironment == null) { + throw new NullPointerException("azureEnvironment"); + } + + this.tenant = tenant; + this.azureEnvironment = azureEnvironment; + this.asymmetricKeyCredential = asymmetricKeyCredential; + + this.credentialType = AzureAdTokenCredentialType.ServicePrincipalWithClientCertificate; + } +} diff --git a/services/azure-media/src/main/java/com/microsoft/windowsazure/services/media/authentication/AzureAdTokenFactory.java b/services/azure-media/src/main/java/com/microsoft/windowsazure/services/media/authentication/AzureAdTokenFactory.java new file mode 100644 index 000000000000..f4ce7d19597a --- /dev/null +++ b/services/azure-media/src/main/java/com/microsoft/windowsazure/services/media/authentication/AzureAdTokenFactory.java @@ -0,0 +1,20 @@ +package com.microsoft.windowsazure.services.media.authentication; + +import java.util.Map; + +import com.microsoft.windowsazure.core.Builder; + +/** + * AzureAdTokenProvider's Factory + * + * Internal use. + */ +public class AzureAdTokenFactory implements Builder.Factory { + + @Override + public TokenProvider create(String profile, Class service, Builder builder, + Map properties) { + return (TokenProvider) properties.get(profile); + } + +} diff --git a/services/azure-media/src/main/java/com/microsoft/windowsazure/services/media/authentication/AzureAdTokenProvider.java b/services/azure-media/src/main/java/com/microsoft/windowsazure/services/media/authentication/AzureAdTokenProvider.java new file mode 100644 index 000000000000..200b5722ed76 --- /dev/null +++ b/services/azure-media/src/main/java/com/microsoft/windowsazure/services/media/authentication/AzureAdTokenProvider.java @@ -0,0 +1,104 @@ +package com.microsoft.windowsazure.services.media.authentication; + +import java.net.MalformedURLException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Future; + +import org.apache.commons.lang.NotImplementedException; + +import com.microsoft.aad.adal4j.AuthenticationContext; +import com.microsoft.aad.adal4j.AuthenticationResult; + +/** + * Azure Active Directory Access Token Provider for + * the Azure Media Services JDK. + */ +public class AzureAdTokenProvider implements TokenProvider { + private final AuthenticationContext authenticationContext; + private final AzureAdTokenCredentials tokenCredentials; + private final ExecutorService executorService; + + /** + * Creates an instance of the AzureAdTokenProvider + * @param tokenCredentials The credentials + * @param executorService An ExecutorService + * @throws MalformedURLException + */ + public AzureAdTokenProvider(AzureAdTokenCredentials tokenCredentials, ExecutorService executorService) throws MalformedURLException { + if (tokenCredentials == null) { + throw new NullPointerException("tokenCredentials"); + } + + if (executorService == null) { + throw new NullPointerException("executorService"); + } + + this.tokenCredentials = tokenCredentials; + + StringBuilder authority = new StringBuilder(); + + authority.append(canonicalizeUri(this.tokenCredentials.getAzureEnvironment().getActiveDirectoryEndpoint().toString())); + authority.append(tokenCredentials.getTenant()); + + this.executorService = executorService; + this.authenticationContext = new AuthenticationContext(authority.toString(), false, this.executorService); + } + + /** + * Acquires an access token + * @see com.microsoft.windowsazure.services.media.authentication.TokenProvider#acquireAccessToken() + */ + @Override + public AzureAdAccessToken acquireAccessToken() throws Exception { + AuthenticationResult authResult = getToken().get(); + return new AzureAdAccessToken(authResult.getAccessToken(), authResult.getExpiresOnDate()); + } + + private Future getToken() { + String mediaServicesResource = this.tokenCredentials.getAzureEnvironment().getMediaServicesResource(); + + switch (this.tokenCredentials.getCredentialType()) { + case UserSecretCredential: + return this.authenticationContext.acquireToken( + mediaServicesResource, + this.tokenCredentials.getAzureEnvironment().getMediaServicesSdkClientId(), + this.tokenCredentials.getAzureAdClientUsernamePassword().getUsername(), + this.tokenCredentials.getAzureAdClientUsernamePassword().getPassword(), + null); + + case ServicePrincipalWithClientSymmetricKey: + return this.authenticationContext.acquireToken( + mediaServicesResource, + this.tokenCredentials.getClientKey(), + null); + + case ServicePrincipalWithClientCertificate: + return this.authenticationContext.acquireToken( + mediaServicesResource, + this.tokenCredentials.getAsymmetricKeyCredential(), + null); + + case UserCredential: + throw new NotImplementedException( + String.format( + "Interactive user credential is currently not supported by the java sdk", + this.tokenCredentials.getCredentialType())); + default: + throw new NotImplementedException( + String.format( + "Token Credential type %1 is not supported.", + this.tokenCredentials.getCredentialType())); + } + } + + private String canonicalizeUri(String authority) { + if (authority != null + && !authority.trim().isEmpty() + && !authority.endsWith("/")) { + + authority += "/"; + } + + return authority; + } +} diff --git a/services/azure-media/src/main/java/com/microsoft/windowsazure/services/media/authentication/AzureEnvironment.java b/services/azure-media/src/main/java/com/microsoft/windowsazure/services/media/authentication/AzureEnvironment.java new file mode 100644 index 000000000000..c3998578619e --- /dev/null +++ b/services/azure-media/src/main/java/com/microsoft/windowsazure/services/media/authentication/AzureEnvironment.java @@ -0,0 +1,83 @@ +package com.microsoft.windowsazure.services.media.authentication; + +import java.net.URI; + +/** + * Represents an Azure Environment + */ +public class AzureEnvironment { + + private URI activeDirectoryEndpoint; + + private String mediaServicesResource; + + private String mediaServicesSdkClientId; + + private URI mediaServicesSdkRedirectUri; + + /** + * Gets the Active Directory endpoint. + * @return Active Directory endpoint. + */ + public URI getActiveDirectoryEndpoint() { + return this.activeDirectoryEndpoint; + } + + /** + * Gets the Media Services resource. + * @return Media Services resource + */ + public String getMediaServicesResource() { + return this.mediaServicesResource; + } + + /** + * Gets the Media Services SDK client ID. + * @return Media Services SDK client ID + */ + public String getMediaServicesSdkClientId() { + return this.mediaServicesSdkClientId; + } + + /** + * Gets Media Services SDK application redirect URI. + * @return Media Services SDK application redirect URI. + */ + public URI getMediaServicesSdkRedirectUri() { + return this.mediaServicesSdkRedirectUri; + } + + /** + * Initializes a new instance of the AzureEnvironment class. + * @param activeDirectoryEndpoint The Active Directory endpoint. + * @param mediaServicesResource The Media Services resource. + * @param mediaServicesSdkClientId The Media Services SDK client ID. + * @param mediaServicesSdkRedirectUri The Media Services SDK redirect URI. + */ + public AzureEnvironment( + URI activeDirectoryEndpoint, + String mediaServicesResource, + String mediaServicesSdkClientId, + URI mediaServicesSdkRedirectUri) { + if (activeDirectoryEndpoint == null) { + throw new NullPointerException("activeDirectoryEndpoint"); + } + + if (mediaServicesResource == null || mediaServicesResource.trim().isEmpty()) { + throw new IllegalArgumentException("mediaServicesResource"); + } + + if (mediaServicesSdkClientId == null || mediaServicesSdkClientId.trim().isEmpty()) { + throw new IllegalArgumentException("mediaServicesSdkClientId"); + } + + if (mediaServicesSdkRedirectUri == null) { + throw new NullPointerException("mediaServicesSdkRedirectUri"); + } + + this.activeDirectoryEndpoint = activeDirectoryEndpoint; + this.mediaServicesResource = mediaServicesResource; + this.mediaServicesSdkClientId = mediaServicesSdkClientId; + this.mediaServicesSdkRedirectUri = mediaServicesSdkRedirectUri; + } +} diff --git a/services/azure-media/src/main/java/com/microsoft/windowsazure/services/media/authentication/AzureEnvironmentConstants.java b/services/azure-media/src/main/java/com/microsoft/windowsazure/services/media/authentication/AzureEnvironmentConstants.java new file mode 100644 index 000000000000..ddbd4b5119df --- /dev/null +++ b/services/azure-media/src/main/java/com/microsoft/windowsazure/services/media/authentication/AzureEnvironmentConstants.java @@ -0,0 +1,74 @@ +package com.microsoft.windowsazure.services.media.authentication; + +import java.net.URI; +import java.net.URISyntaxException; + +public final class AzureEnvironmentConstants { + + // Utility classes should not have a public or default constructor. + private AzureEnvironmentConstants() { + } + + /** + * The Active Directory endpoint for Azure Cloud environment. + */ + public static final URI AZURE_CLOUD_ACTIVE_DIRECTORY_ENDPOINT = makeURI("https://login.microsoftonline.com/"); + + /** + * The Media Services resource for Azure Cloud environment. + */ + public static final String AZURE_CLOUD_MEDIA_SERVICES_RESOURCE = "https://rest.media.azure.net"; + + /** + * The Active Directory endpoint for Azure China Cloud environment. + */ + public static final URI AZURE_CHINA_CLOUD_ACTIVE_DIRECTORY_ENDPOINT = makeURI("https://login.chinacloudapi.cn/"); + + /** + * The Media Services resource for Azure China Cloud environment. + */ + public static final String AZURE_CHINA_CLOUD_MEDIA_SERVICES_RESOURCE = "https://rest.media.chinacloudapi.cn"; + + /** + * The Active Directory endpoint for Azure US Government environment. + */ + public static final URI AZURE_US_GOVERNMENT_ACTIVE_DIRECTORY_ENDPOINT = makeURI("https://login-us.microsoftonline.com/"); + + /** + * The Media Services resource for Azure US Government environment. + */ + public static final String AZURE_US_GOVERNMENT_MEDIA_SERVICES_RESOURCE = "https://rest.media.usgovcloudapi.net"; + + /** + * The native SDK AAD application ID for Azure US Government environment. + */ + public static final String AZURE_US_GOVERNMENT_SDK_AAD_APPLIATION_ID = "68dac91e-cab5-461b-ab4a-ec7dcff0bd67"; + + /** + * The Active Directory endpoint for Azure German cloud environment. + */ + public static final URI AZURE_GERMAN_CLOUD_ACTIVE_DIRECTORY_ENDPOINT = makeURI("https://login.microsoftonline.de/"); + + /** + * The Media Services resource for Azure German Cloud environment. + */ + public static final String AZURE_GERMAN_CLOUD_MEDIA_SERVICES_RESOURCE = "https://rest.media.cloudapi.de"; + + /** + * The native SDK AAD application ID for Azure Cloud, Azure China Cloud and Azure German Cloud environment. + */ + public static final String SDK_AAD_APPLICATION_ID = "d476653d-842c-4f52-862d-397463ada5e7"; + + /** + * The native SDK AAD application's redirect URL for all environments. + */ + public static final URI SDK_AAD_APPLICATION_REDIRECT_URI = makeURI("https://AzureMediaServicesNativeSDK"); + + private static URI makeURI(String urlString) { + try { + return new URI(urlString); + } catch (URISyntaxException e) { + return null; + } + } +} diff --git a/services/azure-media/src/main/java/com/microsoft/windowsazure/services/media/authentication/AzureEnvironments.java b/services/azure-media/src/main/java/com/microsoft/windowsazure/services/media/authentication/AzureEnvironments.java new file mode 100644 index 000000000000..f2ad26a38a1b --- /dev/null +++ b/services/azure-media/src/main/java/com/microsoft/windowsazure/services/media/authentication/AzureEnvironments.java @@ -0,0 +1,44 @@ +package com.microsoft.windowsazure.services.media.authentication; + +public final class AzureEnvironments { + + // Utility classes should not have a public or default constructor. + private AzureEnvironments() { + } + + /** + * Azure Cloud environment. + */ + public static final AzureEnvironment AZURE_CLOUD_ENVIRONMENT = new AzureEnvironment( + AzureEnvironmentConstants.AZURE_CLOUD_ACTIVE_DIRECTORY_ENDPOINT, + AzureEnvironmentConstants.AZURE_CLOUD_MEDIA_SERVICES_RESOURCE, + AzureEnvironmentConstants.SDK_AAD_APPLICATION_ID, + AzureEnvironmentConstants.SDK_AAD_APPLICATION_REDIRECT_URI); + + /** + * Azure China Cloud environment. + */ + public static final AzureEnvironment AZURE_CHINA_CLOUD_ENVIRONMENT = new AzureEnvironment( + AzureEnvironmentConstants.AZURE_CHINA_CLOUD_ACTIVE_DIRECTORY_ENDPOINT, + AzureEnvironmentConstants.AZURE_CHINA_CLOUD_MEDIA_SERVICES_RESOURCE, + AzureEnvironmentConstants.SDK_AAD_APPLICATION_ID, + AzureEnvironmentConstants.SDK_AAD_APPLICATION_REDIRECT_URI); + + /** + * Azure US Government environment. + */ + public static final AzureEnvironment AZURE_US_GOVERNMENT_ENVIRONMENT = new AzureEnvironment( + AzureEnvironmentConstants.AZURE_US_GOVERNMENT_ACTIVE_DIRECTORY_ENDPOINT, + AzureEnvironmentConstants.AZURE_US_GOVERNMENT_MEDIA_SERVICES_RESOURCE, + AzureEnvironmentConstants.AZURE_US_GOVERNMENT_SDK_AAD_APPLIATION_ID, + AzureEnvironmentConstants.SDK_AAD_APPLICATION_REDIRECT_URI); + + /** + * Azure German Cloud environment. + */ + public static final AzureEnvironment AZURE_GERMAN_CLOUD_ENVIRONMENT = new AzureEnvironment( + AzureEnvironmentConstants.AZURE_GERMAN_CLOUD_ACTIVE_DIRECTORY_ENDPOINT, + AzureEnvironmentConstants.AZURE_GERMAN_CLOUD_MEDIA_SERVICES_RESOURCE, + AzureEnvironmentConstants.SDK_AAD_APPLICATION_ID, + AzureEnvironmentConstants.SDK_AAD_APPLICATION_REDIRECT_URI); +} diff --git a/services/azure-media/src/main/java/com/microsoft/windowsazure/services/media/authentication/TokenProvider.java b/services/azure-media/src/main/java/com/microsoft/windowsazure/services/media/authentication/TokenProvider.java new file mode 100644 index 000000000000..ca4e9b62156f --- /dev/null +++ b/services/azure-media/src/main/java/com/microsoft/windowsazure/services/media/authentication/TokenProvider.java @@ -0,0 +1,13 @@ +package com.microsoft.windowsazure.services.media.authentication; + +public interface TokenProvider { + + /** + * Acquire an access token + * + * @return a valid access token + * @throws Exception + */ + AzureAdAccessToken acquireAccessToken() throws Exception; + +} diff --git a/services/azure-media/src/main/java/com/microsoft/windowsazure/services/media/authentication/package-info.java b/services/azure-media/src/main/java/com/microsoft/windowsazure/services/media/authentication/package-info.java new file mode 100644 index 000000000000..bd769aaa63ca --- /dev/null +++ b/services/azure-media/src/main/java/com/microsoft/windowsazure/services/media/authentication/package-info.java @@ -0,0 +1 @@ +package com.microsoft.windowsazure.services.media.authentication; \ No newline at end of file diff --git a/services/azure-media/src/main/java/com/microsoft/windowsazure/services/media/implementation/OAuthContract.java b/services/azure-media/src/main/java/com/microsoft/windowsazure/services/media/implementation/OAuthContract.java deleted file mode 100644 index 1b570cdc5a2f..000000000000 --- a/services/azure-media/src/main/java/com/microsoft/windowsazure/services/media/implementation/OAuthContract.java +++ /dev/null @@ -1,45 +0,0 @@ -/** - * Copyright Microsoft Corporation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.microsoft.windowsazure.services.media.implementation; - -import java.net.URI; - -import com.microsoft.windowsazure.exception.ServiceException; - -public interface OAuthContract { - /** - * Gets an OAuth access token with specified OAUTH URI, client ID, client - * secret, and scope. - * - * @param oAuthUri - * A URI object which represents an OAUTH URI. - * - * @param clientId - * A String object which represents a client ID. - * - * @param clientSecret - * A String object which represents a client secret. - * - * @param scope - * A String object which represents the scope. - * - * @return OAuthTokenResponse - * @throws ServiceException - */ - OAuthTokenResponse getAccessToken(URI oAuthUri, String clientId, - String clientSecret, String scope) throws ServiceException; - -} diff --git a/services/azure-media/src/main/java/com/microsoft/windowsazure/services/media/implementation/OAuthFilter.java b/services/azure-media/src/main/java/com/microsoft/windowsazure/services/media/implementation/OAuthFilter.java index 26583f42a967..23f1122ed770 100644 --- a/services/azure-media/src/main/java/com/microsoft/windowsazure/services/media/implementation/OAuthFilter.java +++ b/services/azure-media/src/main/java/com/microsoft/windowsazure/services/media/implementation/OAuthFilter.java @@ -1,11 +1,11 @@ /* * Copyright Microsoft Corporation - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -14,52 +14,51 @@ */ package com.microsoft.windowsazure.services.media.implementation; -import java.net.URISyntaxException; +import javax.inject.Named; import com.microsoft.windowsazure.core.pipeline.jersey.IdempotentClientFilter; -import com.microsoft.windowsazure.exception.ServiceException; +import com.microsoft.windowsazure.services.media.MediaConfiguration; +import com.microsoft.windowsazure.services.media.authentication.AzureAdAccessToken; +import com.microsoft.windowsazure.services.media.authentication.TokenProvider; import com.sun.jersey.api.client.ClientHandlerException; import com.sun.jersey.api.client.ClientRequest; import com.sun.jersey.api.client.ClientResponse; /** * The Jersey filter for OAuth. - * + * */ public class OAuthFilter extends IdempotentClientFilter { - private final OAuthTokenManager oAuthTokenManager; + private final TokenProvider azureAdTokenProvider; /** * Creates an OAuthFilter object with specified - * OAuthTokenManager instance. - * - * @param oAuthTokenManager + * TokenProvider instance. + * + * @param azureAdTokenProvider */ - public OAuthFilter(OAuthTokenManager oAuthTokenManager) { - this.oAuthTokenManager = oAuthTokenManager; + public OAuthFilter(@Named(MediaConfiguration.AZURE_AD_TOKEN_PROVIDER) TokenProvider azureAdTokenProvider) { + this.azureAdTokenProvider = azureAdTokenProvider; } /* * (non-Javadoc) - * + * * @see * com.microsoft.windowsazure.services.core.IdempotentClientFilter#doHandle * (com.sun.jersey.api.client.ClientRequest) - */@Override + */ + @Override public ClientResponse doHandle(ClientRequest clientRequest) { - String accessToken; + AzureAdAccessToken accessToken; + try { - accessToken = oAuthTokenManager.getAccessToken(); - } catch (ServiceException e) { - // must wrap exception because of base class signature - throw new ClientHandlerException(e); - } catch (URISyntaxException e) { - // must wrap exception because of base class signature - throw new ClientHandlerException(e); + accessToken = azureAdTokenProvider.acquireAccessToken(); + } catch (Exception e) { + throw new ClientHandlerException("Failed to acquire access token", e); } - clientRequest.getHeaders() - .add("Authorization", "Bearer " + accessToken); + clientRequest.getHeaders().add("Authorization", "Bearer " + accessToken.getAccessToken()); return this.getNext().handle(clientRequest); } diff --git a/services/azure-media/src/main/java/com/microsoft/windowsazure/services/media/implementation/OAuthRestProxy.java b/services/azure-media/src/main/java/com/microsoft/windowsazure/services/media/implementation/OAuthRestProxy.java deleted file mode 100644 index b5d4a1794ce9..000000000000 --- a/services/azure-media/src/main/java/com/microsoft/windowsazure/services/media/implementation/OAuthRestProxy.java +++ /dev/null @@ -1,142 +0,0 @@ -/** - * Copyright Microsoft Corporation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.microsoft.windowsazure.services.media.implementation; - -import java.io.IOException; -import java.net.URI; - -import javax.inject.Inject; -import javax.ws.rs.core.MediaType; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; -import org.codehaus.jackson.JsonParseException; -import org.codehaus.jackson.map.JsonMappingException; -import org.codehaus.jackson.map.ObjectMapper; -import org.codehaus.jackson.type.TypeReference; - -import com.microsoft.windowsazure.core.UserAgentFilter; -import com.microsoft.windowsazure.core.pipeline.jersey.ClientFilterRequestAdapter; -import com.microsoft.windowsazure.exception.ServiceException; -import com.microsoft.windowsazure.exception.ServiceExceptionFactory; -import com.sun.jersey.api.client.Client; -import com.sun.jersey.api.client.ClientResponse; -import com.sun.jersey.api.client.UniformInterfaceException; -import com.sun.jersey.api.representation.Form; - -/** - * The OAuth rest proxy. - * - */ -public class OAuthRestProxy implements OAuthContract { - private Client channel; - - private final String grantType = "client_credentials"; - - private static Log log = LogFactory.getLog(OAuthContract.class); - - @Inject - public OAuthRestProxy(Client channel, UserAgentFilter userAgentFilter) { - this.channel = channel; - channel.addFilter(new ClientFilterRequestAdapter(userAgentFilter)); - } - - /** - * Gets an OAuth access token with specified OAUTH URI, client ID, client - * secret, and scope. - * - * @param oAuthUri - * A URI object which represents an OAUTH URI. - * - * @param clientId - * A String object which represents a client ID. - * - * @param clientSecret - * A String object which represents a client secret. - * - * @param scope - * A String object which represents the scope. - * - * @return OAuthTokenResponse - * @throws ServiceException - */ - @Override - public OAuthTokenResponse getAccessToken(URI oAuthUri, String clientId, - String clientSecret, String scope) throws ServiceException { - OAuthTokenResponse response = null; - Form requestForm = new Form(); - ClientResponse clientResponse; - String responseJson; - - requestForm.add("grant_type", grantType); - requestForm.add("client_id", clientId); - requestForm.add("client_secret", clientSecret); - requestForm.add("scope", scope); - - try { - clientResponse = channel.resource(oAuthUri) - .accept(MediaType.APPLICATION_FORM_URLENCODED) - .type(MediaType.APPLICATION_FORM_URLENCODED) - .post(ClientResponse.class, requestForm); - } catch (UniformInterfaceException e) { - log.warn("OAuth server returned error acquiring access_token", e); - throw ServiceExceptionFactory - .process( - "OAuth", - new ServiceException( - "OAuth server returned error acquiring access_token", - e)); - } - - responseJson = clientResponse.getEntity(String.class); - - try { - ObjectMapper mapper = new ObjectMapper(); - TypeReference typeReference = new TypeReference() { - }; - response = mapper.readValue(responseJson, typeReference); - } catch (JsonParseException e) { - log.warn( - "The response from OAuth server cannot be parsed correctly", - e); - throw ServiceExceptionFactory - .process( - "OAuth", - new ServiceException( - "The response from OAuth server cannot be parsed correctly", - e)); - } catch (JsonMappingException e) { - log.warn( - "The response from OAuth server cannot be mapped to OAuthResponse object", - e); - throw ServiceExceptionFactory - .process( - "OAuth", - new ServiceException( - "The response from OAuth server cannot be mapped to OAuthResponse object", - e)); - } catch (IOException e) { - log.warn("Cannot map the response from OAuth server correctly.", e); - throw ServiceExceptionFactory - .process( - "OAuth", - new ServiceException( - "Cannot map the response from OAuth server correctly.", - e)); - } - - return response; - } -} diff --git a/services/azure-media/src/main/java/com/microsoft/windowsazure/services/media/implementation/OAuthTokenManager.java b/services/azure-media/src/main/java/com/microsoft/windowsazure/services/media/implementation/OAuthTokenManager.java deleted file mode 100644 index ba5507ce95ac..000000000000 --- a/services/azure-media/src/main/java/com/microsoft/windowsazure/services/media/implementation/OAuthTokenManager.java +++ /dev/null @@ -1,112 +0,0 @@ -/** - * Copyright Microsoft Corporation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.microsoft.windowsazure.services.media.implementation; - -import java.net.URI; -import java.net.URISyntaxException; -import java.util.Date; - -import javax.inject.Named; -import javax.management.timer.Timer; - -import com.microsoft.windowsazure.core.utils.DateFactory; -import com.microsoft.windowsazure.exception.ServiceException; -import com.microsoft.windowsazure.services.media.MediaConfiguration; - -/** - * An OAuth token manager class. - * - */ -public class OAuthTokenManager { - private final DateFactory dateFactory; - private final URI acsBaseUri; - private final String clientId; - private final String clientSecret; - private final OAuthContract contract; - private ActiveToken activeToken; - private final String scope; - - /** - * Creates an OAuth token manager instance with specified contract, date - * factory, ACS base URI, client ID, and client secret. - * - * @param contract - * A OAuthContract object instance that represents - * the OAUTH contract. - * - * @param dateFactory - * A DateFactory object instance that represents the - * date factory. - * - * @param oAuthUri - * A String object instance that represents the ACS - * base URI. - * - * @param clientId - * A String object instance that represents the - * client ID. - * - * @param clientSecret - * A String object instance that represents the - * client secret. - * @throws URISyntaxException - * - */ - public OAuthTokenManager(OAuthContract contract, DateFactory dateFactory, - @Named(MediaConfiguration.OAUTH_URI) String oAuthUri, - @Named(MediaConfiguration.OAUTH_CLIENT_ID) String clientId, - @Named(MediaConfiguration.OAUTH_CLIENT_SECRET) String clientSecret, - @Named(MediaConfiguration.OAUTH_SCOPE) String scope) - throws URISyntaxException { - this.contract = contract; - this.dateFactory = dateFactory; - this.acsBaseUri = new URI(oAuthUri); - this.clientId = clientId; - this.clientSecret = clientSecret; - this.scope = scope; - this.activeToken = null; - } - - /** - * Gets an OAuth access token with specified media service scope. - * - * @param mediaServiceScope - * A String instance that represents the media - * service scope. - * - * @return String - * - * @throws ServiceException - * @throws URISyntaxException - */ - public String getAccessToken() throws ServiceException, URISyntaxException { - Date now = dateFactory.getDate(); - if (this.activeToken == null - || now.after(this.activeToken.getExpiresUtc())) { - OAuthTokenResponse oAuth2TokenResponse = contract.getAccessToken( - acsBaseUri, clientId, clientSecret, scope); - Date expiresUtc = new Date(now.getTime() - + oAuth2TokenResponse.getExpiresIn() * Timer.ONE_SECOND / 2); - - ActiveToken newToken = new ActiveToken(); - newToken.setAccessToken(oAuth2TokenResponse.getAccessToken()); - newToken.setExpiresUtc(expiresUtc); - - this.activeToken = newToken; - } - return this.activeToken.getAccessToken(); - } -} diff --git a/services/azure-media/src/main/java/com/microsoft/windowsazure/services/media/implementation/OAuthTokenResponse.java b/services/azure-media/src/main/java/com/microsoft/windowsazure/services/media/implementation/OAuthTokenResponse.java deleted file mode 100644 index 1a124d4dd662..000000000000 --- a/services/azure-media/src/main/java/com/microsoft/windowsazure/services/media/implementation/OAuthTokenResponse.java +++ /dev/null @@ -1,75 +0,0 @@ -/** - * Copyright Microsoft Corporation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.microsoft.windowsazure.services.media.implementation; - -import org.codehaus.jackson.annotate.JsonProperty; - -/** - * A class representing OAuth token response. - * - */ -public class OAuthTokenResponse { - - private String accessToken; - private String scope; - private String tokenType; - private long expiresIn; - - /** - * Sets the token type. - * - * @param tokenType - */ - @JsonProperty("token_type") - public void setTokenType(String tokenType) { - this.tokenType = tokenType; - } - - @JsonProperty("token_type") - public String getTokenType() { - return tokenType; - } - - @JsonProperty("expires_in") - public long getExpiresIn() { - return expiresIn; - } - - @JsonProperty("expires_in") - public void setExpiresIn(long expiresIn) { - this.expiresIn = expiresIn; - } - - @JsonProperty("access_token") - public String getAccessToken() { - return accessToken; - } - - @JsonProperty("access_token") - public void setAccessToken(String accessToken) { - this.accessToken = accessToken; - } - - @JsonProperty("scope") - public String getScope() { - return scope; - } - - @JsonProperty("scope") - public void setScope(String scope) { - this.scope = scope; - } -} diff --git a/services/azure-media/src/main/java/com/microsoft/windowsazure/services/media/implementation/ResourceLocationManager.java b/services/azure-media/src/main/java/com/microsoft/windowsazure/services/media/implementation/ResourceLocationManager.java index 5923b8bcc0d5..19300b5ba264 100644 --- a/services/azure-media/src/main/java/com/microsoft/windowsazure/services/media/implementation/ResourceLocationManager.java +++ b/services/azure-media/src/main/java/com/microsoft/windowsazure/services/media/implementation/ResourceLocationManager.java @@ -26,7 +26,7 @@ public class ResourceLocationManager { private URI baseURI; - public ResourceLocationManager(@Named(MediaConfiguration.URI) String baseUri) + public ResourceLocationManager(@Named(MediaConfiguration.AZURE_AD_API_SERVER) String baseUri) throws URISyntaxException { this.baseURI = new URI(baseUri); } diff --git a/services/azure-media/src/main/java/com/microsoft/windowsazure/services/media/implementation/SASTokenFilter.java b/services/azure-media/src/main/java/com/microsoft/windowsazure/services/media/implementation/SASTokenFilter.java index d91f0391a1a5..7f631b8ff4b0 100644 --- a/services/azure-media/src/main/java/com/microsoft/windowsazure/services/media/implementation/SASTokenFilter.java +++ b/services/azure-media/src/main/java/com/microsoft/windowsazure/services/media/implementation/SASTokenFilter.java @@ -55,7 +55,7 @@ public ClientResponse doHandle(ClientRequest cr) { } else if (currentQuery.length() > 0) { currentQuery += "&"; } - currentQuery += sasToken; + currentQuery += "api-version=2016-05-31&" + sasToken; newUri.replaceQuery(currentQuery); cr.setURI(newUri.build()); diff --git a/services/azure-media/src/main/java/com/microsoft/windowsazure/services/media/implementation/VersionHeadersFilter.java b/services/azure-media/src/main/java/com/microsoft/windowsazure/services/media/implementation/VersionHeadersFilter.java index 7701c2d3db90..bba0269d4752 100644 --- a/services/azure-media/src/main/java/com/microsoft/windowsazure/services/media/implementation/VersionHeadersFilter.java +++ b/services/azure-media/src/main/java/com/microsoft/windowsazure/services/media/implementation/VersionHeadersFilter.java @@ -40,7 +40,7 @@ public ClientResponse doHandle(ClientRequest cr) { MultivaluedMap headers = cr.getHeaders(); headers.add("DataServiceVersion", "3.0"); headers.add("MaxDataServiceVersion", "3.0"); - headers.add("x-ms-version", "2.13"); + headers.add("x-ms-version", "2.17"); return getNext().handle(cr); } } diff --git a/services/azure-media/src/main/java/com/microsoft/windowsazure/services/media/models/StreamingEndpoint.java b/services/azure-media/src/main/java/com/microsoft/windowsazure/services/media/models/StreamingEndpoint.java index f75405f27c93..93391379b74c 100644 --- a/services/azure-media/src/main/java/com/microsoft/windowsazure/services/media/models/StreamingEndpoint.java +++ b/services/azure-media/src/main/java/com/microsoft/windowsazure/services/media/models/StreamingEndpoint.java @@ -1,11 +1,11 @@ /** * Copyright Microsoft Corporation - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -40,7 +40,7 @@ /** * Class for creating operations to manipulate Asset entities. - * + * */ public final class StreamingEndpoint { @@ -56,7 +56,7 @@ private StreamingEndpoint() { /** * Creates an Asset Creator. - * + * * @return the creator */ public static Creator create() { @@ -96,6 +96,7 @@ public Object processResponse(Object rawResponse) throws ServiceException { ClientResponse clientResponse = (ClientResponse) rawResponse; if (clientResponse.getStatus() >= 300) { + clientResponse.bufferEntity(); throw new UniformInterfaceException( String.format("Received: %s", clientResponse.getEntity(String.class)), clientResponse); } @@ -113,7 +114,7 @@ public Object processResponse(Object rawResponse) throws ServiceException { /* * (non-Javadoc) - * + * * @see com.microsoft.windowsazure.services.media.entityoperations. * EntityCreateOperation#getRequestContents() */ @@ -133,7 +134,7 @@ public Object getRequestContents() { /** * Set the name of the streaming endpoint to be created. - * + * * @param name * The name * @return The creator object (for call chaining) @@ -145,7 +146,7 @@ public Creator setName(String name) { /** * Set the description of the streaming endpoint to be created. - * + * * @param description * The description * @return The creator object (for call chaining) @@ -157,7 +158,7 @@ public Creator setDescription(String description) { /** * Set the scale units of the streaming endpoint to be created. - * + * * @param scaleUnits * the scale units * @return The creator object (for call chaining) @@ -169,7 +170,7 @@ public Creator setScaleUnits(int scaleUnits) { /** * Set if CDN is enabled on the streaming endpoint to be created. - * + * * @param cdnEnabled * true if CDN is enabled * @return The creator object (for call chaining) @@ -182,7 +183,7 @@ public Creator setCdnEnabled(boolean cdnEnabled) { /** * Set the access control policies of the streaming endpoint to be * created. - * + * * @param streamingEndpointAccessControl * the access control policies * @return The creator object (for call chaining) @@ -195,7 +196,7 @@ public Creator setAccessControl(StreamingEndpointAccessControlType streamingEndp /** * Set the list of custom host names of the streaming endpoint to be * created. - * + * * @param customHostNames * the list of custom host names * @return The creator object (for call chaining) @@ -208,7 +209,7 @@ public Creator setCustomHostNames(List customHostNames) { /** * Set the streaming endpoint cache control of the streaming endpoint to * be created. - * + * * @param streamingEndpointCacheControl * the streaming endpoint cache control * @return The creator object (for call chaining) @@ -221,7 +222,7 @@ public Creator setCacheControl(StreamingEndpointCacheControlType streamingEndpoi /** * Set the cross site access policies of the streaming endpoint to be * created. - * + * * @param crossSiteAccessPolicies * the cross site access policies * @return The creator object (for call chaining) @@ -235,7 +236,7 @@ public Creator setCrossSiteAccessPolicies(CrossSiteAccessPoliciesType crossSiteA /** * Create an operation object that will get the state of the given asset. - * + * * @param assetId * id of asset to retrieve * @return the get operation @@ -247,7 +248,7 @@ public static EntityGetOperation get(String streamingEndp /** * Create an operation that will list all the assets. - * + * * @return The list operation */ public static DefaultListOperation list() { @@ -258,7 +259,7 @@ public static DefaultListOperation list() { /** * Create an operation that will update the given asset. - * + * * @param assetId * id of the asset to update * @return the update operation @@ -285,7 +286,7 @@ public static class Updater extends EntityOperationBase implements EntityUpdateO /** * Instantiates a new updater. - * + * * @param assetId * the asset id */ @@ -305,7 +306,7 @@ protected Updater(StreamingEndpointInfo streamingEndpointInfo) { /* * (non-Javadoc) - * + * * @see com.microsoft.windowsazure.services.media.entityoperations. * EntityOperation * #setProxyData(com.microsoft.windowsazure.services.media @@ -318,7 +319,7 @@ public void setProxyData(EntityProxyData proxyData) { /* * (non-Javadoc) - * + * * @see com.microsoft.windowsazure.services.media.entityoperations. * EntityUpdateOperation#getRequestContents() */ @@ -336,7 +337,7 @@ public Object getRequestContents() { /** * Set the new description of the streaming endpoint to be updated. - * + * * @param description * The description * @return The creator object (for call chaining) @@ -349,7 +350,7 @@ public Updater setDescription(String description) { /** * Set the new value for CDN enabled on the streaming endpoint to be * updated. - * + * * @param cdnEnabled * true if CDN is enabled * @return The creator object (for call chaining) @@ -362,7 +363,7 @@ public Updater setCdnEnabled(boolean cdnEnabled) { /** * Set the new access control policies of the streaming endpoint to be * updated. - * + * * @param streamingEndpointAccessControl * the access control policies * @return The creator object (for call chaining) @@ -375,7 +376,7 @@ public Updater setAccessControl(StreamingEndpointAccessControlType streamingEndp /** * Set the new list of custom host names of the streaming endpoint to be * updated. - * + * * @param customHostNames * the list of custom host names * @return The creator object (for call chaining) @@ -388,7 +389,7 @@ public Updater setCustomHostNames(List customHostNames) { /** * Set the new streaming endpoint cache control of the streaming * endpoint to be updated. - * + * * @param streamingEndpointCacheControl * the streaming endpoint cache control * @return The creator object (for call chaining) @@ -401,7 +402,7 @@ public Updater setCacheControl(StreamingEndpointCacheControlType streamingEndpoi /** * Set the new cross site access policies of the streaming endpoint to * be updated. - * + * * @param crossSiteAccessPolicies * the cross site access policies * @return The creator object (for call chaining) @@ -414,7 +415,7 @@ public Updater setCrossSiteAccessPolicies(CrossSiteAccessPoliciesType crossSiteA /** * Create an operation to delete the given streaming endpoint - * + * * @param assetId * id of asset to delete * @return the delete operation diff --git a/services/azure-media/src/test/java/com/microsoft/windowsazure/media/authentication/AzureAdTokenProviderTest.java b/services/azure-media/src/test/java/com/microsoft/windowsazure/media/authentication/AzureAdTokenProviderTest.java new file mode 100644 index 000000000000..6e44272f2c61 --- /dev/null +++ b/services/azure-media/src/test/java/com/microsoft/windowsazure/media/authentication/AzureAdTokenProviderTest.java @@ -0,0 +1,118 @@ +package com.microsoft.windowsazure.media.authentication; + +import static org.junit.Assert.*; +import static org.junit.Assume.*; + +import java.io.FileInputStream; +import java.io.InputStream; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + +import org.junit.AfterClass; +import org.junit.BeforeClass; +import org.junit.Test; + +import com.microsoft.aad.adal4j.AsymmetricKeyCredential; +import com.microsoft.windowsazure.Configuration; +import com.microsoft.windowsazure.exception.ServiceException; +import com.microsoft.windowsazure.services.media.IntegrationTestBase; +import com.microsoft.windowsazure.services.media.MediaConfiguration; +import com.microsoft.windowsazure.services.media.MediaContract; +import com.microsoft.windowsazure.services.media.MediaService; +import com.microsoft.windowsazure.services.media.authentication.AzureAdClientSymmetricKey; +import com.microsoft.windowsazure.services.media.authentication.AzureAdClientUsernamePassword; +import com.microsoft.windowsazure.services.media.authentication.AzureAdTokenCredentials; +import com.microsoft.windowsazure.services.media.authentication.AzureAdTokenProvider; +import com.microsoft.windowsazure.services.media.authentication.AzureEnvironments; +import com.microsoft.windowsazure.services.media.authentication.TokenProvider; +import com.microsoft.windowsazure.services.media.models.Asset; +import com.microsoft.windowsazure.services.media.models.AssetInfo; +import com.microsoft.windowsazure.services.media.models.ListResult; + +public class AzureAdTokenProviderTest extends IntegrationTestBase { + + @Test + public void ServicePrincipalClientSymmetricKeyShouldWork() throws Exception { + // Arrange + String tenant = config.getProperty("media.azuread.test.tenant").toString(); + String restApiEndpoint = config.getProperty("media.azuread.test.account_api_uri").toString(); + String clientId = config.getProperty("media.azuread.test.clientid").toString(); + String clientKey = config.getProperty("media.azuread.test.clientkey").toString(); + AzureAdTokenCredentials credentials = new AzureAdTokenCredentials( + tenant, + new AzureAdClientSymmetricKey(clientId, clientKey), + AzureEnvironments.AZURE_CLOUD_ENVIRONMENT); + TokenProvider provider = new AzureAdTokenProvider(credentials, executorService); + Configuration configuration = MediaConfiguration.configureWithAzureAdTokenProvider( + new URI(restApiEndpoint), + provider); + MediaContract mediaService = MediaService.create(configuration); + + // Act + ListResult assets = mediaService.list(Asset.list()); + + // Assert + assertNotNull(assets); + } + + @Test + public void UserPasswordShouldWork() throws Exception { + // Arrange + String tenant = config.getProperty("media.azuread.test.tenant").toString(); + String restApiEndpoint = config.getProperty("media.azuread.test.account_api_uri").toString(); + String username = config.getProperty("media.azuread.test.useraccount").toString(); + String password = config.getProperty("media.azuread.test.userpassword").toString(); + + assumeFalse(username.equals("undefined")); + assumeFalse(password.equals("undefined")); + + AzureAdTokenCredentials credentials = new AzureAdTokenCredentials( + tenant, + new AzureAdClientUsernamePassword(username, password), + AzureEnvironments.AZURE_CLOUD_ENVIRONMENT); + TokenProvider provider = new AzureAdTokenProvider(credentials, executorService); + Configuration configuration = MediaConfiguration.configureWithAzureAdTokenProvider( + new URI(restApiEndpoint), + provider); + MediaContract mediaService = MediaService.create(configuration); + + // Act + ListResult assets = mediaService.list(Asset.list()); + + // Assert + assertNotNull(assets); + } + + @Test + public void ServicePrincipalWithCertificateShouldWork() throws Exception { + // Arrange + String tenant = config.getProperty("media.azuread.test.tenant").toString(); + String restApiEndpoint = config.getProperty("media.azuread.test.account_api_uri").toString(); + String clientId = config.getProperty("media.azuread.test.clientid").toString(); + String pfxFile = config.getProperty("media.azuread.test.pfxfile").toString(); + String pfxPassword = config.getProperty("media.azuread.test.pfxpassword").toString(); + + assumeFalse(pfxFile.equals("undefined")); + assumeFalse(pfxPassword.equals("undefined")); + + InputStream pfx = new FileInputStream(pfxFile); + AzureAdTokenCredentials credentials = new AzureAdTokenCredentials( + tenant, + AsymmetricKeyCredential.create(clientId, pfx, pfxPassword), + AzureEnvironments.AZURE_CLOUD_ENVIRONMENT); + TokenProvider provider = new AzureAdTokenProvider(credentials, executorService); + Configuration configuration = MediaConfiguration.configureWithAzureAdTokenProvider( + new URI(restApiEndpoint), + provider); + MediaContract mediaService = MediaService.create(configuration); + + // Act + ListResult assets = mediaService.list(Asset.list()); + + // Assert + assertNotNull(assets); + } +} diff --git a/services/azure-media/src/test/java/com/microsoft/windowsazure/media/authentication/package-info.java b/services/azure-media/src/test/java/com/microsoft/windowsazure/media/authentication/package-info.java new file mode 100644 index 000000000000..4374821a2931 --- /dev/null +++ b/services/azure-media/src/test/java/com/microsoft/windowsazure/media/authentication/package-info.java @@ -0,0 +1 @@ +package com.microsoft.windowsazure.media.authentication; \ No newline at end of file diff --git a/services/azure-media/src/test/java/com/microsoft/windowsazure/services/media/ExportsTest.java b/services/azure-media/src/test/java/com/microsoft/windowsazure/services/media/ExportsTest.java index f1f2e390c2a0..2e166db4fb4a 100644 --- a/services/azure-media/src/test/java/com/microsoft/windowsazure/services/media/ExportsTest.java +++ b/services/azure-media/src/test/java/com/microsoft/windowsazure/services/media/ExportsTest.java @@ -37,7 +37,7 @@ public void canResolveLocationManagerFromConfig() throws Exception { ResourceLocationManager rlm = config .create(ResourceLocationManager.class); URI rootUri = new URI( - (String) config.getProperty(MediaConfiguration.URI)); + (String) config.getProperty(MediaConfiguration.AZURE_AD_API_SERVER)); assertEquals(rootUri, rlm.getBaseURI()); } diff --git a/services/azure-media/src/test/java/com/microsoft/windowsazure/services/media/IntegrationTestBase.java b/services/azure-media/src/test/java/com/microsoft/windowsazure/services/media/IntegrationTestBase.java index a823dd94a085..731348634a40 100644 --- a/services/azure-media/src/test/java/com/microsoft/windowsazure/services/media/IntegrationTestBase.java +++ b/services/azure-media/src/test/java/com/microsoft/windowsazure/services/media/IntegrationTestBase.java @@ -22,12 +22,15 @@ import java.io.ByteArrayInputStream; import java.io.InputStream; import java.lang.reflect.Method; +import java.net.URI; import java.util.ArrayList; import java.util.Collection; import java.util.Date; import java.util.EnumSet; import java.util.List; import java.util.UUID; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; import org.junit.AfterClass; import org.junit.BeforeClass; @@ -36,6 +39,11 @@ import com.microsoft.windowsazure.Configuration; import com.microsoft.windowsazure.exception.ServiceException; +import com.microsoft.windowsazure.services.media.authentication.AzureAdClientSymmetricKey; +import com.microsoft.windowsazure.services.media.authentication.AzureAdTokenCredentials; +import com.microsoft.windowsazure.services.media.authentication.AzureAdTokenProvider; +import com.microsoft.windowsazure.services.media.authentication.AzureEnvironments; +import com.microsoft.windowsazure.services.media.authentication.TokenProvider; import com.microsoft.windowsazure.services.media.models.AccessPolicy; import com.microsoft.windowsazure.services.media.models.AccessPolicyInfo; import com.microsoft.windowsazure.services.media.models.AccessPolicyPermission; @@ -68,7 +76,9 @@ public abstract class IntegrationTestBase { protected static MediaContract service; protected static QueueContract queueService; protected static Configuration config; - + protected static ExecutorService executorService; + protected static TokenProvider tokenProvider; + protected static final String testAssetPrefix = "testAsset"; protected static final String testPolicyPrefix = "testPolicy"; protected static final String testContentKeyPrefix = "testContentKey"; @@ -83,7 +93,7 @@ public abstract class IntegrationTestBase { protected static final String validButNonexistAccessPolicyId = "nb:pid:UUID:38dcb3a0-ef64-4ad0-bbb5-67a14c6df2f7"; protected static final String validButNonexistLocatorId = "nb:lid:UUID:92a70402-fca9-4aa3-80d7-d4de3792a27a"; - protected static String MEDIA_ENCODER_MEDIA_PROCESSOR_ID = "nb:mpid:UUID:2e7aa8f3-4961-4e0c-b4db-0e0439e524f5"; + protected static String MEDIA_ENCODER_MEDIA_PROCESSOR_ID = "nb:mpid:UUID:ff4df607-d419-42f0-bc17-a481b1331e56"; protected static final String invalidId = "notAValidId"; @Rule @@ -91,13 +101,26 @@ public abstract class IntegrationTestBase { @BeforeClass public static void setup() throws Exception { - config = Configuration.getInstance(); - overrideWithEnv(config, MediaConfiguration.URI); - overrideWithEnv(config, MediaConfiguration.OAUTH_URI); - overrideWithEnv(config, MediaConfiguration.OAUTH_CLIENT_ID); - overrideWithEnv(config, MediaConfiguration.OAUTH_CLIENT_SECRET); - overrideWithEnv(config, MediaConfiguration.OAUTH_SCOPE); - + executorService = Executors.newFixedThreadPool(5); + config = Configuration.getInstance(); + + String tenant = config.getProperty("media.azuread.test.tenant").toString(); + String clientId = config.getProperty("media.azuread.test.clientid").toString(); + String clientKey = config.getProperty("media.azuread.test.clientkey").toString(); + String apiserver = config.getProperty("media.azuread.test.account_api_uri").toString(); + + // Setup Azure AD Credentials (in this case using username and password) + AzureAdTokenCredentials credentials = new AzureAdTokenCredentials( + tenant, + new AzureAdClientSymmetricKey(clientId, clientKey), + AzureEnvironments.AZURE_CLOUD_ENVIRONMENT); + + tokenProvider = new AzureAdTokenProvider(credentials, executorService); + + // configure the account endpoint and the token provider for injection + config.setProperty(MediaConfiguration.AZURE_AD_API_SERVER, apiserver); + config.setProperty(MediaConfiguration.AZURE_AD_TOKEN_PROVIDER, tokenProvider); + overrideWithEnv(config, QueueConfiguration.ACCOUNT_KEY, "media.queue.account.key"); overrideWithEnv(config, QueueConfiguration.ACCOUNT_NAME, @@ -150,6 +173,9 @@ protected static void overrideWithEnv(Configuration config, String key, @AfterClass public static void cleanup() throws Exception { cleanupEnvironment(); + + // shutdown the executor service required by ADAL4J + executorService.shutdown(); } protected static void cleanupEnvironment() { diff --git a/services/azure-media/src/test/java/com/microsoft/windowsazure/services/media/JobIntegrationTest.java b/services/azure-media/src/test/java/com/microsoft/windowsazure/services/media/JobIntegrationTest.java index 562169fd9f3c..a5bdc5bea3c1 100644 --- a/services/azure-media/src/test/java/com/microsoft/windowsazure/services/media/JobIntegrationTest.java +++ b/services/azure-media/src/test/java/com/microsoft/windowsazure/services/media/JobIntegrationTest.java @@ -516,7 +516,7 @@ public void canGetTaskHistoricalEventsFromTask() throws Exception { TaskHistoricalEvent historicalEvent = historicalEvents.get(0); // Assert - assertTrue(historicalEvents.size() >= 5); + assertTrue(historicalEvents.size() >= 4); assertNotNull(historicalEvent.getCode()); assertNotNull(historicalEvent.getTimeStamp()); assertNull(historicalEvent.getMessage()); diff --git a/services/azure-media/src/test/java/com/microsoft/windowsazure/services/media/MediaConfigurationTest.java b/services/azure-media/src/test/java/com/microsoft/windowsazure/services/media/MediaConfigurationTest.java deleted file mode 100644 index a99a361d87f1..000000000000 --- a/services/azure-media/src/test/java/com/microsoft/windowsazure/services/media/MediaConfigurationTest.java +++ /dev/null @@ -1,102 +0,0 @@ -/** - * Copyright Microsoft Corporation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.microsoft.windowsazure.services.media; - -import static org.junit.Assert.assertEquals; - -import org.junit.Test; - -import com.microsoft.windowsazure.Configuration; - -public class MediaConfigurationTest { - - @Test - public void createMediaConfigurationTestSuccess() { - // Arrange - - // Act - Configuration configuration = MediaConfiguration - .configureWithOAuthAuthentication( - "https://testMediaServiceBaseUri", "testOAuthUri", - "testClientId", "testClientSecret", "testScope"); - - // Assert - assertEquals("https://testMediaServiceBaseUri", - configuration.getProperty("media.uri")); - assertEquals("testOAuthUri", - configuration.getProperty("media.oauth.uri")); - assertEquals("testClientId", - configuration.getProperty("media.oauth.client.id")); - assertEquals("testClientSecret", - configuration.getProperty("media.oauth.client.secret")); - assertEquals("testScope", - configuration.getProperty("media.oauth.scope")); - } - - @Test - public void createMediaConfigurationPassingExistingConfigurationSuccess() { - // Arrange - Configuration preConfiguration = new Configuration(); - preConfiguration.setProperty("preexistingName", "preexistingValue"); - - // Act - Configuration configuration = MediaConfiguration - .configureWithOAuthAuthentication(preConfiguration, - "https://testMediaServiceBaseUri", "testOAuthUri", - "testClientId", "testClientSecret", "testScope"); - - // Assert - assertEquals("preexistingValue", - configuration.getProperty("preexistingName")); - assertEquals("https://testMediaServiceBaseUri", - configuration.getProperty("media.uri")); - assertEquals("testOAuthUri", - configuration.getProperty("media.oauth.uri")); - assertEquals("testClientId", - configuration.getProperty("media.oauth.client.id")); - assertEquals("testClientSecret", - configuration.getProperty("media.oauth.client.secret")); - - } - - @Test - public void createMediaConfigurationWithProfileConfigurationSuccess() { - // Arrange - Configuration preConfiguration = new Configuration(); - preConfiguration.setProperty("preexistingName", "preexistingValue"); - - // Act - Configuration configuration = MediaConfiguration - .configureWithOAuthAuthentication("testProfile", - preConfiguration, "https://testMediaServiceBaseUri", - "testOAuthUri", "testClientId", "testClientSecret", - "testScope"); - - // Assert - assertEquals("preexistingValue", - configuration.getProperty("preexistingName")); - assertEquals("https://testMediaServiceBaseUri", - configuration.getProperty("testProfile.media.uri")); - assertEquals("testOAuthUri", - configuration.getProperty("testProfile.media.oauth.uri")); - assertEquals("testClientId", - configuration.getProperty("testProfile.media.oauth.client.id")); - assertEquals("testClientSecret", - configuration - .getProperty("testProfile.media.oauth.client.secret")); - } - -} diff --git a/services/azure-media/src/test/java/com/microsoft/windowsazure/services/media/MediaServiceTest.java b/services/azure-media/src/test/java/com/microsoft/windowsazure/services/media/MediaServiceTest.java deleted file mode 100644 index 812217008246..000000000000 --- a/services/azure-media/src/test/java/com/microsoft/windowsazure/services/media/MediaServiceTest.java +++ /dev/null @@ -1,87 +0,0 @@ -/** - * Copyright Microsoft Corporation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package com.microsoft.windowsazure.services.media; - -import static org.junit.Assert.assertNotNull; - -import org.junit.Test; - -import com.microsoft.windowsazure.Configuration; - -public class MediaServiceTest { - - @Test - public void createMediaContractSuccessTest() { - // Arrange - Configuration configurationInstance = Configuration.getInstance(); - configurationInstance = MediaConfiguration - .configureWithOAuthAuthentication(configurationInstance, - "mediaServiceBaseUri", "oAuthUri", "clientId", - "clientSecret", "testScope"); - - // Act - MediaContract mediaContract = MediaService.create(); - - // Assert - assertNotNull(mediaContract); - configurationInstance = null; - - } - - @Test - public void createMediaContractWithSpecifiedConfigurationTest() { - // Arrange - Configuration configuration = MediaConfiguration - .configureWithOAuthAuthentication("mediaServiceBaseUri", - "oAuthUri", "clientId", "clientSecret", "testScope"); - - // Act - MediaContract mediaContract = MediaService.create(configuration); - - // Assert - assertNotNull(mediaContract); - } - - @Test - public void createMediaContractWithSpecifiedProfileTest() { - // Arrange - String profile = "testProfile"; - - // Act - MediaContract mediaContract = MediaService.create(profile); - - // Assert - assertNotNull(mediaContract); - - } - - @Test - public void createMediaContractWithSpecifiedProfileAndConfiguration() { - // Arrange - String profile = "testProfile"; - Configuration configuration = MediaConfiguration - .configureWithOAuthAuthentication(profile, new Configuration(), - "mediaServiceBaseUri", "oAuthUri", "clientId", - "clientSecret", "testScope"); - - // Act - MediaContract mediaContract = MediaService.create(profile, - configuration); - - // Assert - assertNotNull(mediaContract); - } -} diff --git a/services/azure-media/src/test/java/com/microsoft/windowsazure/services/media/StreamingEndopointIntegrationTest.java b/services/azure-media/src/test/java/com/microsoft/windowsazure/services/media/StreamingEndopointIntegrationTest.java index 24235020b14b..91457c62e792 100644 --- a/services/azure-media/src/test/java/com/microsoft/windowsazure/services/media/StreamingEndopointIntegrationTest.java +++ b/services/azure-media/src/test/java/com/microsoft/windowsazure/services/media/StreamingEndopointIntegrationTest.java @@ -1,11 +1,11 @@ /** * Copyright Microsoft Corporation - * + * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * http://www.apache.org/licenses/LICENSE-2.0 - * + * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. @@ -18,6 +18,7 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; +import static org.junit.Assume.assumeTrue; import java.util.ArrayList; import java.util.Calendar; @@ -43,14 +44,45 @@ public class StreamingEndopointIntegrationTest extends IntegrationTestBase { + @Test + public void streamingEndpointReachEndpointsLimit() throws Exception { + // Arrange + String endpoint1 = testStreamingEndPointPrefix + "ReachEndpointsLimit1"; + String endpoint2 = testStreamingEndPointPrefix + "ReachEndpointsLimit2"; + + StreamingEndpointInfo streamingEndpointInfo = service.create(StreamingEndpoint.create().setName(endpoint1)); + + OperationUtils.await(service, streamingEndpointInfo); + + // Act + try { + StreamingEndpointInfo streamingEndpoint2Info = service.create(StreamingEndpoint.create().setName(endpoint2)); + + // mark this test as ignored if the subscription supports more than 2 streaming endpoints + assumeTrue(streamingEndpoint2Info == null); + + } catch(Exception e) { + + // Assert Act + assertTrue("Error should be ExceededResourceQuota", e.getMessage().contains("ExceededResourceQuota")); + } + + // Cleanup + String deleteOpId = service.delete(StreamingEndpoint.delete(streamingEndpointInfo.getId())); + OperationState state = OperationUtils.await(service, deleteOpId); + + // Assert Cleanup + assertEquals(state, OperationState.Succeeded); + } + @Test public void streamingEndpointCreateListByNameAndDelete() throws Exception { // Arrange String expectedName = testStreamingEndPointPrefix + "ListByNameTest"; StreamingEndpointInfo streamingEndpointInfo = service.create(StreamingEndpoint.create().setName(expectedName)); - + OperationUtils.await(service, streamingEndpointInfo); - + // Act ListResult listStreamingEndpointResult = service.list(StreamingEndpoint.list() .set("$filter", "(Name eq '" + expectedName + "')")); @@ -61,122 +93,123 @@ public void streamingEndpointCreateListByNameAndDelete() throws Exception { StreamingEndpointInfo info = listStreamingEndpointResult.get(0); assertNotNull(info); assertEquals(info.getName(), expectedName); - + // Cleanup String deleteOpId = service.delete(StreamingEndpoint.delete(info.getId())); OperationState state = OperationUtils.await(service, deleteOpId); + // Assert Cleanup assertEquals(state, OperationState.Succeeded); } - + @Test public void streamingEndpointCreateStartStopDeleteTest() throws Exception { // Arrange String expectedName = testStreamingEndPointPrefix + "Startable"; StreamingEndpointInfo streamingEndpointInfo = service.create(StreamingEndpoint.create().setName(expectedName)); - + OperationUtils.await(service, streamingEndpointInfo); - + // Act String startingOpId = service.action(StreamingEndpoint.start(streamingEndpointInfo.getId())); OperationState state = OperationUtils.await(service, startingOpId); - + // Assert - assertEquals(state, OperationState.Succeeded); + assertEquals(state, OperationState.Succeeded); streamingEndpointInfo = service.get(StreamingEndpoint.get(streamingEndpointInfo.getId())); - assertNotNull(streamingEndpointInfo); + assertNotNull(streamingEndpointInfo); assertEquals(StreamingEndpointState.Running, streamingEndpointInfo.getState()); - + // Act 2 - startingOpId = service.action(StreamingEndpoint.stop(streamingEndpointInfo.getId())); + startingOpId = service.action(StreamingEndpoint.stop(streamingEndpointInfo.getId())); state = OperationUtils.await(service, startingOpId); - + // Assert 2 assertEquals(state, OperationState.Succeeded); - + // Cleanup String deleteOpId = service.delete(StreamingEndpoint.delete(streamingEndpointInfo.getId())); state = OperationUtils.await(service, deleteOpId); // Assert Cleanup assertEquals(state, OperationState.Succeeded); } - + @Test public void streamingEndpointCreateStartScaleStopDeleteTest() throws Exception { // Arrange int expectedScaleUnits = 2; String expectedName = testStreamingEndPointPrefix + "Scalable"; StreamingEndpointInfo streamingEndpointInfo = service.create(StreamingEndpoint.create().setName(expectedName)); - + OperationUtils.await(service, streamingEndpointInfo); - + // Act String startingOpId = service.action(StreamingEndpoint.start(streamingEndpointInfo.getId())); OperationState state = OperationUtils.await(service, startingOpId); - + // Assert - assertEquals(state, OperationState.Succeeded); + assertEquals(state, OperationState.Succeeded); streamingEndpointInfo = service.get(StreamingEndpoint.get(streamingEndpointInfo.getId())); - assertNotNull(streamingEndpointInfo); + assertNotNull(streamingEndpointInfo); assertEquals(StreamingEndpointState.Running, streamingEndpointInfo.getState()); - - startingOpId = service.action(StreamingEndpoint.scale(streamingEndpointInfo.getId(), expectedScaleUnits)); + + startingOpId = service.action(StreamingEndpoint.scale(streamingEndpointInfo.getId(), expectedScaleUnits)); state = OperationUtils.await(service, startingOpId); // Assert 3 assertEquals(state, OperationState.Succeeded); streamingEndpointInfo = service.get(StreamingEndpoint.get(streamingEndpointInfo.getId())); assertNotNull(streamingEndpointInfo); assertEquals(expectedScaleUnits, streamingEndpointInfo.getScaleUnits()); - + // Act 3 - startingOpId = service.action(StreamingEndpoint.stop(streamingEndpointInfo.getId())); + startingOpId = service.action(StreamingEndpoint.stop(streamingEndpointInfo.getId())); state = OperationUtils.await(service, startingOpId); // Assert 3 assertEquals(state, OperationState.Succeeded); - + // Cleanup String deleteOpId = service.delete(StreamingEndpoint.delete(streamingEndpointInfo.getId())); state = OperationUtils.await(service, deleteOpId); // Assert Cleanup assertEquals(state, OperationState.Succeeded); } - + @Test public void streamingEndpointEnableCDNTest() throws Exception { // Arrange int expectedScaleUnits = 1; String expectedName = testStreamingEndPointPrefix + "EnableCDN"; - + // Act 1 StreamingEndpointInfo streamingEndpointInfo = service.create(StreamingEndpoint.create().setName(expectedName)); OperationState state = OperationUtils.await(service, streamingEndpointInfo); // Assert 1 - assertEquals(state, OperationState.Succeeded); - + assertEquals(state, OperationState.Succeeded); + // Act 2 String opId = service.action(StreamingEndpoint.scale(streamingEndpointInfo.getId(), expectedScaleUnits)); state = OperationUtils.await(service, opId); // Assert 2 - assertEquals(state, OperationState.Succeeded); - + assertEquals(state, OperationState.Succeeded); + // Act 3 opId = service.update(StreamingEndpoint.update(streamingEndpointInfo).setCdnEnabled(true)); state = OperationUtils.await(service, opId); // Assert 3 - assertEquals(state, OperationState.Succeeded); - + assertEquals(state, OperationState.Succeeded); + // Act 4 streamingEndpointInfo = service.get(StreamingEndpoint.get(streamingEndpointInfo.getId())); // Assert 4 assertTrue(streamingEndpointInfo.isCdnEnabled()); - + // Cleanup String deleteOpId = service.delete(StreamingEndpoint.delete(streamingEndpointInfo.getId())); state = OperationUtils.await(service, deleteOpId); // Assert Cleanup assertEquals(state, OperationState.Succeeded); } - + @Test public void createAndRetrieveTheSameStreamingEndpointTest() throws Exception { // Arrange @@ -188,7 +221,7 @@ public void createAndRetrieveTheSameStreamingEndpointTest() throws Exception { String expectedClientAccessPolicy = ""; String expectedCrossDomainPolicy = ""; String expectedAkamaiIdentifier = "akamaikey"; - + Calendar cal = Calendar.getInstance(); cal.setTime(new Date()); cal.add(Calendar.HOUR, 48); @@ -196,58 +229,58 @@ public void createAndRetrieveTheSameStreamingEndpointTest() throws Exception { String expectedAkamaiB64 = "/31iWKdqNC7YUnj8zQ3XHA=="; String expectedIPAddress = "0.0.0.0"; String expectedIPName = "Allow All"; - + CrossSiteAccessPoliciesType expectedCrossSiteAccessPolicies = new CrossSiteAccessPoliciesType(); expectedCrossSiteAccessPolicies.setClientAccessPolicy(expectedClientAccessPolicy); expectedCrossSiteAccessPolicies.setCrossDomainPolicy(expectedCrossDomainPolicy); - + IPAccessControlType expectedIP = new IPAccessControlType(); expectedIP.setIpRange(new ArrayList()); expectedIP.getIpRange().add(new IPRangeType()); expectedIP.getIpRange().get(0).setAddress(expectedIPAddress); expectedIP.getIpRange().get(0).setName(expectedIPName); expectedIP.getIpRange().get(0).setSubnetPrefixLength(0); - + AkamaiAccessControlType expectedAkamai = new AkamaiAccessControlType(); - List akamaiSignatureHeaderAuthenticationKeyList = + List akamaiSignatureHeaderAuthenticationKeyList = new ArrayList(); akamaiSignatureHeaderAuthenticationKeyList.add(new AkamaiSignatureHeaderAuthenticationKey()); akamaiSignatureHeaderAuthenticationKeyList.get(0).setExpiration(expectedAkamaiExpiration); akamaiSignatureHeaderAuthenticationKeyList.get(0).setId(expectedAkamaiIdentifier); akamaiSignatureHeaderAuthenticationKeyList.get(0).setBase64Key(expectedAkamaiB64); expectedAkamai.setAkamaiSignatureHeaderAuthenticationKeyList(akamaiSignatureHeaderAuthenticationKeyList); - + StreamingEndpointAccessControlType expectedStreamingEndpointAccessControl = new StreamingEndpointAccessControlType(); - expectedStreamingEndpointAccessControl.setAkamai(expectedAkamai); + expectedStreamingEndpointAccessControl.setAkamai(expectedAkamai); expectedStreamingEndpointAccessControl.setIP(expectedIP); - + StreamingEndpointCacheControlType expectedStreamingEndpointCacheControl = new StreamingEndpointCacheControlType(); expectedStreamingEndpointCacheControl.setMaxAge(expectedMaxAge ); - + // Act StreamingEndpointInfo streamingEndpointInfo = service.create( StreamingEndpoint.create() .setName(expectedName) .setCdnEnabled(expectedCdnState) .setDescription(expectedDesc) - .setScaleUnits(expectedScaleUnits) + .setScaleUnits(expectedScaleUnits) .setCrossSiteAccessPolicies(expectedCrossSiteAccessPolicies) .setAccessControl(expectedStreamingEndpointAccessControl) .setCacheControl(expectedStreamingEndpointCacheControl ) ); - + OperationState state = OperationUtils.await(service, streamingEndpointInfo); - + // Act validations assertEquals(OperationState.Succeeded, state); assertNotNull(streamingEndpointInfo); - + // Retrieve the StramingEndpoint again. StreamingEndpointInfo result = service.get(StreamingEndpoint.get(streamingEndpointInfo.getId())); - + // Assert - assertNotNull(result); + assertNotNull(result); assertEquals(result.getScaleUnits(), expectedScaleUnits); assertEquals(result.getName(), expectedName); assertEquals(result.getDescription(), expectedDesc); @@ -255,7 +288,7 @@ public void createAndRetrieveTheSameStreamingEndpointTest() throws Exception { assertEquals(result.getCrossSiteAccessPolicies().getCrossDomainPolicy(), expectedCrossDomainPolicy); assertEquals(result.getCacheControl().getMaxAge(), expectedMaxAge); List akamai = result.getAccessControl().getAkamai().getAkamaiSignatureHeaderAuthenticationKeyList(); - assertNotNull(akamai); + assertNotNull(akamai); assertEquals(akamai.size(), 1); assertEquals(akamai.get(0).getId(), expectedAkamaiIdentifier); assertEquals(akamai.get(0).getExpiration(), expectedAkamaiExpiration); @@ -266,7 +299,7 @@ public void createAndRetrieveTheSameStreamingEndpointTest() throws Exception { assertEquals(ip.get(0).getAddress(), expectedIPAddress); assertEquals(ip.get(0).getName(), expectedIPName); assertEquals(ip.get(0).getSubnetPrefixLength(), 0); - + // Cleanup String deleteOpId = service.delete(StreamingEndpoint.delete(result.getId())); state = OperationUtils.await(service, deleteOpId); diff --git a/services/azure-media/src/test/java/com/microsoft/windowsazure/services/media/TaskIntegrationTest.java b/services/azure-media/src/test/java/com/microsoft/windowsazure/services/media/TaskIntegrationTest.java index c88d71c7ad05..bdb2da64a3f5 100644 --- a/services/azure-media/src/test/java/com/microsoft/windowsazure/services/media/TaskIntegrationTest.java +++ b/services/azure-media/src/test/java/com/microsoft/windowsazure/services/media/TaskIntegrationTest.java @@ -244,8 +244,6 @@ private void verifyTaskProperties(String message, String mediaProcessorId, initializationVector, actual.getInitializationVector()); // Read-only fields - assertDateApproxEquals(message + " getEndTime", endTime, - actual.getEndTime()); assertNotNull(message + " getErrorDetails", actual.getErrorDetails()); assertEquals(message + " getErrorDetails.size", 0, actual .getErrorDetails().size()); @@ -303,7 +301,7 @@ private void verifyTaskPropertiesJustStartedNoEncryption(String message, String configuration, String name, int priority, TaskInfo actual) throws ServiceException { String encryptionKeyId = null; - String encryptionScheme = null; + String encryptionScheme = "None"; String encryptionVersion = null; String initializationVector = null; @@ -320,7 +318,7 @@ private void verifyTaskPropertiesNoEncryption(String message, Date startTime, TaskState state, TaskInfo actual) throws ServiceException { String encryptionKeyId = null; - String encryptionScheme = null; + String encryptionScheme = "None"; String encryptionVersion = null; String initializationVector = null; diff --git a/services/azure-media/src/test/java/com/microsoft/windowsazure/services/media/UploadingIntegrationTest.java b/services/azure-media/src/test/java/com/microsoft/windowsazure/services/media/UploadingIntegrationTest.java index 272ba487dbfd..ffd0f5f07d4d 100644 --- a/services/azure-media/src/test/java/com/microsoft/windowsazure/services/media/UploadingIntegrationTest.java +++ b/services/azure-media/src/test/java/com/microsoft/windowsazure/services/media/UploadingIntegrationTest.java @@ -16,8 +16,10 @@ package com.microsoft.windowsazure.services.media; import java.io.ByteArrayInputStream; +import java.io.IOException; import java.io.InputStream; import java.util.EnumSet; +import java.util.Random; import org.junit.BeforeClass; import org.junit.Test; @@ -69,6 +71,50 @@ public void canUploadBlockBlob() throws Exception { InputStream blobContent = new ByteArrayInputStream(firstPrimes); blobWriter.createBlockBlob("uploadBlockBlobTest", blobContent); } + + @Test + public void canUploadLargeBlockBlob() throws Exception { + + InputStream blobContent = new InputStream() { + private int count = 0; + private int _mark = 0; + private int invalidate = 0; + + private Random rand = new Random(); + + @Override + public int read() throws IOException { + if ((this.count++) > 1024*1024*66) { + return -1; + } + if (invalidate > 0) { + this.invalidate--; + if (this.invalidate == 0) { + this._mark = 0; + } + } + return rand.nextInt(256); + } + + @Override + public void mark(int mark) { + this._mark = this.count; + } + + @Override + public void reset() { + this.count = this._mark; + this._mark = 0; + } + + @Override + public boolean markSupported() { + return true; + } + }; + + blobWriter.createBlockBlob("uploadLargeBlockBlobTest", blobContent); + } @Test public void canUploadBlockBlobWithOptions() throws Exception { diff --git a/services/azure-media/src/test/java/com/microsoft/windowsazure/services/media/implementation/OAuthRestProxyIntegrationTest.java b/services/azure-media/src/test/java/com/microsoft/windowsazure/services/media/implementation/OAuthRestProxyIntegrationTest.java deleted file mode 100644 index 9b87e2031ff4..000000000000 --- a/services/azure-media/src/test/java/com/microsoft/windowsazure/services/media/implementation/OAuthRestProxyIntegrationTest.java +++ /dev/null @@ -1,51 +0,0 @@ -/** - * Copyright Microsoft Corporation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.microsoft.windowsazure.services.media.implementation; - -import static org.junit.Assert.assertNotNull; - -import java.net.URI; - -import org.junit.Test; - -import com.microsoft.windowsazure.core.UserAgentFilter; -import com.microsoft.windowsazure.services.media.IntegrationTestBase; -import com.microsoft.windowsazure.services.media.MediaConfiguration; -import com.sun.jersey.api.client.Client; - -public class OAuthRestProxyIntegrationTest extends IntegrationTestBase { - @Test - public void serviceCanBeCalledToCreateAccessToken() throws Exception { - // Arrange - OAuthContract oAuthContract = new OAuthRestProxy( - config.create(Client.class), new UserAgentFilter()); - - // Act - URI oAuthUri = new URI( - (String) config.getProperty(MediaConfiguration.OAUTH_URI)); - String clientId = (String) config - .getProperty(MediaConfiguration.OAUTH_CLIENT_ID); - String clientSecret = (String) config - .getProperty(MediaConfiguration.OAUTH_CLIENT_SECRET); - String scope = (String) config - .getProperty(MediaConfiguration.OAUTH_SCOPE); - OAuthTokenResponse result = oAuthContract.getAccessToken(oAuthUri, - clientId, clientSecret, scope); - - // Assert - assertNotNull(result); - assertNotNull(result.getAccessToken()); - } -} diff --git a/services/azure-media/src/test/java/com/microsoft/windowsazure/services/media/implementation/OAuthTokenManagerTest.java b/services/azure-media/src/test/java/com/microsoft/windowsazure/services/media/implementation/OAuthTokenManagerTest.java deleted file mode 100644 index f593f87d2d77..000000000000 --- a/services/azure-media/src/test/java/com/microsoft/windowsazure/services/media/implementation/OAuthTokenManagerTest.java +++ /dev/null @@ -1,146 +0,0 @@ -/** - * Copyright Microsoft Corporation - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ -package com.microsoft.windowsazure.services.media.implementation; - -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.mockito.Mockito.doAnswer; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - -import java.io.IOException; -import java.net.URI; -import java.net.URISyntaxException; -import java.util.Calendar; -import java.util.Date; -import java.util.TimeZone; - -import org.junit.Before; -import org.junit.Test; -import org.mockito.invocation.InvocationOnMock; -import org.mockito.stubbing.Answer; - -import com.microsoft.windowsazure.core.utils.DateFactory; -import com.microsoft.windowsazure.exception.ServiceException; - -public class OAuthTokenManagerTest { - private OAuthContract contract; - private OAuthTokenManager client; - private DateFactory dateFactory; - private Calendar calendar; - - @Before - public void init() throws URISyntaxException { - calendar = Calendar.getInstance(TimeZone.getTimeZone("GMT")); - - dateFactory = mock(DateFactory.class); - - // Client channel = new Client(); - contract = mock(OAuthRestProxy.class); - - String acsBaseUri = "testurl"; - String accountName = "testname"; - String accountPassword = "testpassword"; - String scope = "testscope"; - - client = new OAuthTokenManager(contract, dateFactory, acsBaseUri, - accountName, accountPassword, scope); - - when(dateFactory.getDate()).thenAnswer(new Answer() { - @Override - public Date answer(InvocationOnMock invocation) throws Throwable { - return calendar.getTime(); - } - }); - } - - private void doIncrementingTokens() throws ServiceException, - URISyntaxException, IOException { - doAnswer(new Answer() { - int count = 0; - - @Override - public OAuthTokenResponse answer(InvocationOnMock invocation) - throws Throwable { - ++count; - OAuthTokenResponse wrapResponse = new OAuthTokenResponse(); - wrapResponse.setAccessToken("testaccesstoken1-" + count); - wrapResponse.setExpiresIn(83); - return wrapResponse; - } - }).when(contract).getAccessToken(new URI("testurl"), "testname", - "testpassword", "testscope"); - - } - - @Test - public void clientUsesContractToGetToken() throws ServiceException, - URISyntaxException, IOException { - // Arrange - doIncrementingTokens(); - - // Act - String accessToken = client.getAccessToken(); - - // Assert - assertNotNull(accessToken); - assertEquals("testaccesstoken1-1", accessToken); - } - - @Test - public void clientWillNotCallMultipleTimesWhileAccessTokenIsValid() - throws ServiceException, URISyntaxException, IOException { - // Arrange - doIncrementingTokens(); - - // Act - String accessToken1 = client.getAccessToken(); - String accessToken2 = client.getAccessToken(); - calendar.add(Calendar.SECOND, 40); - String accessToken3 = client.getAccessToken(); - - // Assert - assertEquals("testaccesstoken1-1", accessToken1); - assertEquals("testaccesstoken1-1", accessToken2); - assertEquals("testaccesstoken1-1", accessToken3); - - verify(contract, times(1)).getAccessToken(new URI("testurl"), - "testname", "testpassword", "testscope"); - } - - @Test - public void clientWillBeCalledWhenTokenIsHalfwayToExpiring() - throws ServiceException, URISyntaxException, IOException { - // Arrange - doIncrementingTokens(); - - // Act - String accessToken1 = client.getAccessToken(); - String accessToken2 = client.getAccessToken(); - calendar.add(Calendar.SECOND, 45); - String accessToken3 = client.getAccessToken(); - - // Assert - assertEquals("testaccesstoken1-1", accessToken1); - assertEquals("testaccesstoken1-1", accessToken2); - assertEquals("testaccesstoken1-2", accessToken3); - - verify(contract, times(2)).getAccessToken(new URI("testurl"), - "testname", "testpassword", "testscope"); - } - -} diff --git a/services/azure-media/src/test/java/com/microsoft/windowsazure/services/media/implementation/ODataSerializationFromJerseyTest.java b/services/azure-media/src/test/java/com/microsoft/windowsazure/services/media/implementation/ODataSerializationFromJerseyTest.java index 81521a3f1bb8..1cbb12fc34e9 100644 --- a/services/azure-media/src/test/java/com/microsoft/windowsazure/services/media/implementation/ODataSerializationFromJerseyTest.java +++ b/services/azure-media/src/test/java/com/microsoft/windowsazure/services/media/implementation/ODataSerializationFromJerseyTest.java @@ -28,6 +28,7 @@ import com.microsoft.windowsazure.services.media.IntegrationTestBase; import com.microsoft.windowsazure.services.media.MediaConfiguration; import com.microsoft.windowsazure.services.media.MediaContract; +import com.microsoft.windowsazure.services.media.authentication.AzureAdTokenProvider; import com.microsoft.windowsazure.services.media.implementation.content.AssetType; import com.microsoft.windowsazure.services.media.models.Asset; import com.microsoft.windowsazure.services.media.models.AssetInfo; @@ -54,7 +55,7 @@ public void canBuildJerseyClientToCreateAnAssetWhichIsProperlyDeserialized() // c.addFilter(new LoggingFilter(System.out)); c.addFilter(new RedirectFilter(createLocationManager())); - c.addFilter(new OAuthFilter(createTokenManager())); + c.addFilter(new OAuthFilter(tokenProvider)); c.addFilter(new VersionHeadersFilter()); WebResource assetResource = c.resource("Assets"); @@ -74,25 +75,10 @@ public void canBuildJerseyClientToCreateAnAssetWhichIsProperlyDeserialized() Assert.assertEquals("some external id", newAsset.getAlternateId()); } - private OAuthContract createOAuthContract() { - return new OAuthRestProxy(Client.create(), new UserAgentFilter()); - } - - private OAuthTokenManager createTokenManager() throws URISyntaxException { - return new OAuthTokenManager( - createOAuthContract(), - new DefaultDateFactory(), - (String) config.getProperty(MediaConfiguration.OAUTH_URI), - (String) config.getProperty(MediaConfiguration.OAUTH_CLIENT_ID), - (String) config - .getProperty(MediaConfiguration.OAUTH_CLIENT_SECRET), - (String) config.getProperty(MediaConfiguration.OAUTH_SCOPE)); - } - private ResourceLocationManager createLocationManager() throws URISyntaxException { return new ResourceLocationManager( - (String) config.getProperty(MediaConfiguration.URI)); + (String) config.getProperty(MediaConfiguration.AZURE_AD_API_SERVER)); } @Test diff --git a/services/azure-media/src/test/java/com/microsoft/windowsazure/services/scenarios/MediaServiceScenarioTest.java b/services/azure-media/src/test/java/com/microsoft/windowsazure/services/scenarios/MediaServiceScenarioTest.java index 66dbd7420f51..44ae452e53da 100644 --- a/services/azure-media/src/test/java/com/microsoft/windowsazure/services/scenarios/MediaServiceScenarioTest.java +++ b/services/azure-media/src/test/java/com/microsoft/windowsazure/services/scenarios/MediaServiceScenarioTest.java @@ -61,6 +61,7 @@ public static void cleanup() throws ServiceException { wrapper.removeAllAssetsWithPrefix(rootTestAssetPrefix); wrapper.removeAllAccessPoliciesWithPrefix(); wrapper.removeAllJobWithPrefix(testJobPrefix); + ScenarioTestBase.cleanupConfig(); } @Test diff --git a/services/azure-media/src/test/java/com/microsoft/windowsazure/services/scenarios/MediaServiceWrapper.java b/services/azure-media/src/test/java/com/microsoft/windowsazure/services/scenarios/MediaServiceWrapper.java index 2968f64f4835..26b5d99e8052 100644 --- a/services/azure-media/src/test/java/com/microsoft/windowsazure/services/scenarios/MediaServiceWrapper.java +++ b/services/azure-media/src/test/java/com/microsoft/windowsazure/services/scenarios/MediaServiceWrapper.java @@ -77,7 +77,7 @@ class MediaServiceWrapper { private static final String accessPolicyPrefix = "scenarioTestPrefix"; private final String MEDIA_PROCESSOR_STORAGE_DECRYPTION = "Storage Decryption"; - private final String MEDIA_PROCESSOR_WINDOWS_AZURE_MEDIA_ENCODER = "Windows Azure Media Encoder"; + private final String MEDIA_PROCESSOR_WINDOWS_AZURE_MEDIA_ENCODER = "Media Encoder Standard"; public static enum EncoderType { WindowsAzureMediaEncoder, StorageDecryption diff --git a/services/azure-media/src/test/java/com/microsoft/windowsazure/services/scenarios/ScenarioTestBase.java b/services/azure-media/src/test/java/com/microsoft/windowsazure/services/scenarios/ScenarioTestBase.java index 37963980d5a4..9aa6ac457453 100644 --- a/services/azure-media/src/test/java/com/microsoft/windowsazure/services/scenarios/ScenarioTestBase.java +++ b/services/azure-media/src/test/java/com/microsoft/windowsazure/services/scenarios/ScenarioTestBase.java @@ -17,6 +17,12 @@ import static org.junit.Assert.fail; +import java.net.MalformedURLException; +import java.net.URI; +import java.net.URISyntaxException; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; + import org.junit.Rule; import org.junit.rules.MethodRule; import org.junit.runners.model.FrameworkMethod; @@ -25,37 +31,46 @@ import com.microsoft.windowsazure.Configuration; import com.microsoft.windowsazure.services.blob.BlobConfiguration; import com.microsoft.windowsazure.services.media.MediaConfiguration; +import com.microsoft.windowsazure.services.media.authentication.AzureAdClientSymmetricKey; +import com.microsoft.windowsazure.services.media.authentication.AzureAdTokenCredentials; +import com.microsoft.windowsazure.services.media.authentication.AzureAdTokenProvider; +import com.microsoft.windowsazure.services.media.authentication.AzureEnvironments; +import com.microsoft.windowsazure.services.media.authentication.TokenProvider; import com.microsoft.windowsazure.services.queue.QueueConfiguration; public abstract class ScenarioTestBase { protected static Configuration config; + protected static ExecutorService executorService; @Rule public SetupManager setupManager = new SetupManager(); protected static void initializeConfig() { - config = new Configuration(); - - overrideWithEnv(config, BlobConfiguration.ACCOUNT_NAME); - overrideWithEnv(config, BlobConfiguration.ACCOUNT_KEY); - overrideWithEnv(config, BlobConfiguration.URI); - - overrideWithEnv(config, QueueConfiguration.ACCOUNT_NAME); - overrideWithEnv(config, QueueConfiguration.ACCOUNT_KEY); - overrideWithEnv(config, QueueConfiguration.URI); - - overrideWithEnv(config, MediaConfiguration.URI); - overrideWithEnv(config, MediaConfiguration.OAUTH_URI); - overrideWithEnv(config, MediaConfiguration.OAUTH_CLIENT_ID); - overrideWithEnv(config, MediaConfiguration.OAUTH_CLIENT_SECRET); - overrideWithEnv(config, MediaConfiguration.OAUTH_SCOPE); - - config = Configuration.getInstance(); - overrideWithEnv(config, MediaConfiguration.URI); - overrideWithEnv(config, MediaConfiguration.OAUTH_URI); - overrideWithEnv(config, MediaConfiguration.OAUTH_CLIENT_ID); - overrideWithEnv(config, MediaConfiguration.OAUTH_CLIENT_SECRET); - overrideWithEnv(config, MediaConfiguration.OAUTH_SCOPE); + executorService = Executors.newFixedThreadPool(5); + config = Configuration.getInstance(); + + String tenant = config.getProperty("media.azuread.test.tenant").toString(); + String clientId = config.getProperty("media.azuread.test.clientid").toString(); + String clientKey = config.getProperty("media.azuread.test.clientkey").toString(); + String apiserver = config.getProperty("media.azuread.test.account_api_uri").toString(); + + // Setup Azure AD Credentials (in this case using username and password) + AzureAdTokenCredentials credentials = new AzureAdTokenCredentials( + tenant, + new AzureAdClientSymmetricKey(clientId, clientKey), + AzureEnvironments.AZURE_CLOUD_ENVIRONMENT); + + TokenProvider provider = null; + + try { + provider = new AzureAdTokenProvider(credentials, executorService); + } catch (MalformedURLException e) { + throw new RuntimeException(e); + } + + // configure the account endpoint and the token provider for injection + config.setProperty(MediaConfiguration.AZURE_AD_API_SERVER, apiserver); + config.setProperty(MediaConfiguration.AZURE_AD_TOKEN_PROVIDER, provider); overrideWithEnv(config, QueueConfiguration.ACCOUNT_KEY, "media.queue.account.key"); @@ -63,6 +78,12 @@ protected static void initializeConfig() { "media.queue.account.name"); overrideWithEnv(config, QueueConfiguration.URI, "media.queue.uri"); } + + protected static void cleanupConfig() { + + // shutdown the executor service required by ADAL4J + executorService.shutdown(); + } private static void overrideWithEnv(Configuration config, String key) { String value = System.getenv(key); @@ -127,5 +148,5 @@ public void evaluate() throws Throwable { } } } - } + } } diff --git a/services/azure-media/src/test/resources/META-INF/com.microsoft.windowsazure.properties b/services/azure-media/src/test/resources/META-INF/com.microsoft.windowsazure.properties index eb2c358c922c..9291222647c9 100644 --- a/services/azure-media/src/test/resources/META-INF/com.microsoft.windowsazure.properties +++ b/services/azure-media/src/test/resources/META-INF/com.microsoft.windowsazure.properties @@ -1,27 +1,19 @@ -serviceBus.uri=https://%SERVICEBUS_NAMESPACE%.servicebus.windows.net/ -serviceBus.wrap.uri=https://%SERVICEBUS_NAMESPACE%-sb.accesscontrol.windows.net/WRAPv0.9 -serviceBus.wrap.name=%SERVICEBUS_SERVICEIDENTITY% -serviceBus.wrap.password=%SERVICEBUS_SHAREDSECRET% -serviceBus.connection.string=EndPoint=sb://%SERVICEBUS_NAMESPACE%.servicebus.windows.net/;SharedSecretIssuer=%SERVICEBUS_SERVICEIDENTITY%;SharedSecretValue=%SERVICEBUS_SHAREDSECRET% -blob.accountName=%BLOB_ACCOUNTNAME% -blob.accountKey=%BLOB_ACCOUNTKEY% -blob.uri=http://%BLOB_ACCOUNTNAME%.blob.core.windows.net -queue.accountName=%QUEUE_ACCOUNTNAME% -queue.accountKey=%QUEUE_ACCOUNTKEY% -queue.uri=http://%QUEUE_ACCOUNTNAME%.queue.core.windows.net -table.accountName=%TABLE_ACCOUNTNAME% -table.accountKey=%TABLE_ACCOUNTKEY% -table.uri=http://%TABLE_ACCOUNTNAME%.table.core.windows.net -media.uri=%MEDIA.URI% -media.oauth.uri=%MEDIA.OAUTH.URI% -media.oauth.client.id=%OMEDIA.AUTH.CLIENT.ID% -media.oauth.client.secret=%MEDIA.OAUTH.CLIENT.SECRET% -media.oauth.scope=urn:WindowsAzureMediaServices -management.keystore.path=%MANAGEMENT.KEYSTORE.PATH% -management.keystore.password=%MANAGEMENT.KEYSTORE.PASSWORD% -management.keystore.type=%MANAGEMENT.KEYSTORE.TYPE% -management.subscription.id=%MANAGEMENT.SUBSCRIPTION.ID% -management.uri=%MANAGEMENT.URI% +blob.accountName= +blob.accountKey= +blob.uri= +queue.accountName= +queue.accountKey= +queue.uri= +table.accountName= +table.accountKey= +table.uri= testprefix.com.microsoft.windowsazure.services.core.Configuration.connectTimeout=3 testprefix.com.microsoft.windowsazure.services.core.Configuration.readTimeout=7 - +media.azuread.test.tenant= +media.azuread.test.clientid= +media.azuread.test.clientkey= +media.azuread.test.account_api_uri= +media.azuread.test.useraccount=undefined +media.azuread.test.userpassword=undefined +media.azuread.test.pfxfile=undefined +media.azuread.test.pfxpassword=undefined