java.lang.Object
↳androidx.security.app.authenticator.TestAppAuthenticatorBuilder
Gradle dependencies
compile group: 'androidx.security', name: 'security-app-authenticator-testing', version: '1.0.0-alpha01'
- groupId: androidx.security
- artifactId: security-app-authenticator-testing
- version: 1.0.0-alpha01
Artifact androidx.security:security-app-authenticator-testing:1.0.0-alpha01 it located at Google repository (https://maven.google.com/)
Overview
Builder class that can be used to facilitate the creation of a new AppAuthenticator which
can be configured to meet the requirements of the test. Similar to the AppAuthenticator,
the static factory methods for this class require either an XML resource or java.io.InputStream
containing the app-authenticator configuration allowing verification of your declared
config as part of the test.
There are several options to configure the behavior of the resulting AppAuthenticator.
Summary
Fields |
---|
public static final int | POLICY_CUSTOM This test policy indicates that the caller will specify the expected results for each
package individually. |
public static final int | POLICY_DENY_ALL This test policy will cause the AppAuthenticator to return that the signing identity of
the package does that match the expect identity from the XML configuration for all queried
packages. |
public static final int | POLICY_SIGNATURE_ACCEPTED_FOR_DECLARED_PACKAGES This test policy will cause the AppAuthenticator to return a successful signing identity for
all packages explicitly declared in the XML configuration. |
Methods |
---|
public AppAuthenticator | build()
Builds an AppAuthenticator with the specified config that can be injected to satisfy
test requirements. |
public static TestAppAuthenticatorBuilder | createFromInputStream(Context context, java.io.InputStream xmlInputStream)
Returns a new TestAppAuthenticatorBuilder that can be used to create a new AppAuthenticator configured to behave as required for the test. |
public static TestAppAuthenticatorBuilder | createFromResource(Context context, int xmlResource)
Returns a new TestAppAuthenticatorBuilder that can be used to create a new AppAuthenticator configured to behave as required for the test. |
public TestAppAuthenticatorBuilder | setPackageNotInstalled(java.lang.String packageName)
Treats the provided packageName as not being installed by the resulting AppAuthenticator. |
public TestAppAuthenticatorBuilder | setSignatureAcceptedForPackage(java.lang.String packageName)
Configures the resulting AppAuthenticator to always return that the signing
identity matches the expected value when the specified packageName is queried. |
public TestAppAuthenticatorBuilder | setSigningIdentityForPackage(java.lang.String packageName, java.lang.String certDigest)
Sets the provided certDigest as the signing identity for the specified packageName. |
public TestAppAuthenticatorBuilder | setTestPolicy(int testPolicy)
Sets the policy to be used by the AppAuthenticator for the test. |
public TestAppAuthenticatorBuilder | setUidForPackage(java.lang.String packageName, int uid)
Sets the provided uid as the UID of the specified packageName. |
from java.lang.Object | clone, equals, finalize, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait |
Fields
public static final int
POLICY_SIGNATURE_ACCEPTED_FOR_DECLARED_PACKAGESThis test policy will cause the AppAuthenticator to return a successful signing identity for
all packages explicitly declared in the XML configuration. This is the default policy used
when a new AppAuthenticator is built without calling TestAppAuthenticatorBuilder.setSigningIdentityForPackage(String, String), TestAppAuthenticatorBuilder.setSignatureAcceptedForPackage(String), and TestAppAuthenticatorBuilder.setPackageNotInstalled(String).
public static final int
POLICY_DENY_ALLThis test policy will cause the AppAuthenticator to return that the signing identity of
the package does that match the expect identity from the XML configuration for all queried
packages.
public static final int
POLICY_CUSTOMThis test policy indicates that the caller will specify the expected results for each
package individually. This is the default policy used when a new TestAppAuthenticator
is built after calling any of the following:
TestAppAuthenticatorBuilder.setSigningIdentityForPackage(String, String), TestAppAuthenticatorBuilder.setSignatureAcceptedForPackage(String), and TestAppAuthenticatorBuilder.setPackageNotInstalled(String).
Once the policy has been set to this value it cannot be changed to any of the other policies.
Methods
Returns a new TestAppAuthenticatorBuilder that can be used to create a new AppAuthenticator configured to behave as required for the test.
Parameters:
context: the context within which to create the AppAuthenticator
xmlResource: the ID of the XML resource containing the definitions for the
permissions and expected identities based on package / expected signing
certificate digests
Returns:
this instance of the TestAppAuthenticatorBuilder
Returns a new TestAppAuthenticatorBuilder that can be used to create a new AppAuthenticator configured to behave as required for the test.
Parameters:
context: the context within which to create the AppAuthenticator
xmlInputStream: the XML java.io.InputStream
containing the definitions for the
permissions and expected identities based on packages / expected
signing certificate digests
Returns:
this instance of the TestAppAuthenticatorBuilder
Sets the policy to be used by the AppAuthenticator for the test.
Parameters:
testPolicy: the test policy to be used by the AppAuthenticator{}
Returns:
this instance of the TestAppAuthenticatorBuilder
See also: TestAppAuthenticatorBuilder.POLICY_SIGNATURE_ACCEPTED_FOR_DECLARED_PACKAGES, TestAppAuthenticatorBuilder.POLICY_DENY_ALL, TestAppAuthenticatorBuilder.POLICY_CUSTOM
Configures the resulting AppAuthenticator to always return that the signing
identity matches the expected value when the specified packageName is queried.
Note, the specified packageName must be defined either explicitly via a
package element or implicitly via a all-packages element; this ensures
that the XML configuration is correct and that the specified package could be verified
on device.
Parameters:
packageName: the name of the package for which the signing identity should be
treated as matching the expected value
Returns:
this instance of the TestAppAuthenticatorBuilder
Sets the provided certDigest as the signing identity for the specified packageName.
Parameters:
packageName: the name of the package that will use the provided signing identity
certDigest: the digest to be treated as the signing identity of the specified package
Returns:
this instance of the TestAppAuthenticatorBuilder
Sets the provided uid as the UID of the specified packageName.
This method can be used to verify the scenario where a calling package does not have the
expected calling UID.
Parameters:
packageName: the name of the package that will be treated as having the provided uid
uid: the uid to use for the specified package
Returns:
this instance of the TestAppAuthenticatorBuilder
Treats the provided packageName as not being installed by the resulting AppAuthenticator.
Parameters:
packageName: the name of the package to be treated as not installed
Returns:
this instance of the TestAppAuthenticatorBuilder
Builds an AppAuthenticator with the specified config that can be injected to satisfy
test requirements.
Returns:
a new AppAuthenticator that will respond to queries as configured
Source
/*
* Copyright 2021 The Android Open Source Project
*
* 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 androidx.security.app.authenticator;
import android.annotation.SuppressLint;
import android.content.Context;
import android.content.res.Resources;
import android.os.Binder;
import androidx.annotation.IntDef;
import androidx.annotation.NonNull;
import androidx.annotation.XmlRes;
import org.xmlpull.v1.XmlPullParser;
import org.xmlpull.v1.XmlPullParserException;
import org.xmlpull.v1.XmlPullParserFactory;
import java.io.IOException;
import java.io.InputStream;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
/**
* Builder class that can be used to facilitate the creation of a new {@link AppAuthenticator} which
* can be configured to meet the requirements of the test. Similar to the {@code AppAuthenticator},
* the static factory methods for this class require either an XML resource or {@link InputStream}
* containing the {@code app-authenticator} configuration allowing verification of your declared
* config as part of the test.
*
* <p>There are several options to configure the behavior of the resulting {@code AppAuthenticator}.
* <ul>
* <li>{@link #setTestPolicy(int)} - This sets a generic test policy. {@link
* #POLICY_SIGNATURE_ACCEPTED_FOR_DECLARED_PACKAGES} will cause the {@code AppAuthenticator}
* to always return that a queried package has the expected signing identity as long as it is
* explicitly declared in your configuration; that is, the package must be declared in a
* {@code package} element within either an {@code expected-identity} or {@code permission}
* element. {@link #POLICY_DENY_ALL} will cause the {@code AppAuthenticator} to always return
* that a queried package does not have the expected signing identity regardless of its
* declaration. These two policies can be used to verify good path and error path for
* scenarios where the package names can be explicitly declared in the XML configuration.
* <p>{@code POLICY_SIGNATURE_ACCEPTED_FOR_DECLARED_PACKAGES} is the default policy when no
* other options are configured. When any of the other set methods (except for {@link
* #setUidForPackage(String, int)}) are invoked they will set the policy to {@link
* #POLICY_CUSTOM}.
* </li>
* <li>{@link #setSignatureAcceptedForPackage(String)} - This configures the {@code
* AppAuthenticator} to always return that the specified package has the expected signing
* identity. Note this still requires the {@code app-authenticator} have a path to verify
* the provided package; that is, the package must either be explicitly declared in a
* {@code package} element or fall under a {@code all-packages} element for the query being
* performed. This is to ensure that a package being verified during the test could also be
* successfully verified in production for the given query.
* </li>
* <li>{@link #setSigningIdentityForPackage(String, String)} - This sets an explicit
* signing identity for the provided package; the signing identity should be
* specified as the SHA-256 digest of the DER encoding of the signing certificate, similar
* to how digests are specified in the {@code app-authenticator} configuration file. While
* this can be used to set a signing identity to the expected value, this is more often
* used to set the signing identity to a value that should not be accepted. For instance, a
* test suite could have a test that verifies a key that is no longer trusted is never
* added back to the configuration file.
* </li>
* <li>{@link #setPackageNotInstalled(String)} - This configures the {@code AppAuthenticator}
* to treat the specified package as not installed on the device. Since a package that is not
* installed can result in a different return code from the {@code AppAuthenticator} methods
* this configuration can be used to verify an app's behavior when an expected app is not
* installed on the device.
* </li>
* <li>{@link #setUidForPackage(String, int)} - The {@code AppAuthenticator} will
* always verify the UID of the calling package matches the specified UID (or
* {@link Binder#getCallingUid()} if a UID is not specified). By default this test {@code
* AppAuthenticator} will use the result of {@code Binder#getCallingUid()} as the UID of all
* queried packages. This method can be used to verify the expected behavior when a calling
* package's UID does not match the expected UID.
* </li>
* </ul>
*/
// The purpose of this class is to build a configurable AppAuthenticator for tests so the builder
// is the top level class.
@SuppressLint("TopLevelBuilder")
public final class TestAppAuthenticatorBuilder {
private Context mContext;
private XmlPullParser mParser;
private @TestPolicy int mTestPolicy;
private TestAppSignatureVerifier.Builder mAppSignatureVerifierBuilder;
private TestAppAuthenticatorUtils.Builder mAppAuthenticatorUtilsBuilder;
/**
* Private constructor that should only be called by the static factory methods.
*
* @param context the context within which to create the {@link AppAuthenticator}
* @param parser an {@link XmlPullParser} containing the definitions for the
* permissions and expected identities based on package / expected signing
* certificate digests
*/
private TestAppAuthenticatorBuilder(Context context, XmlPullParser parser) {
mContext = context;
mParser = parser;
mTestPolicy = POLICY_SIGNATURE_ACCEPTED_FOR_DECLARED_PACKAGES;
mAppSignatureVerifierBuilder = new TestAppSignatureVerifier.Builder(context);
mAppAuthenticatorUtilsBuilder = new TestAppAuthenticatorUtils.Builder(mContext);
}
/**
* This test policy will cause the AppAuthenticator to return a successful signing identity for
* all packages explicitly declared in the XML configuration. This is the default policy used
* when a new {@code AppAuthenticator} is built without calling {@link
* #setSigningIdentityForPackage(String, String)}, {@link
* #setSignatureAcceptedForPackage(String)}, and {@link #setPackageNotInstalled(String)}.
*/
public static final int POLICY_SIGNATURE_ACCEPTED_FOR_DECLARED_PACKAGES = 1;
/**
* This test policy will cause the AppAuthenticator to return that the signing identity of
* the package does that match the expect identity from the XML configuration for all queried
* packages.
*/
public static final int POLICY_DENY_ALL = 2;
/**
* This test policy indicates that the caller will specify the expected results for each
* package individually. This is the default policy used when a new {@code TestAppAuthenticator}
* is built after calling any of the following:
* {@link #setSigningIdentityForPackage(String, String)}, {@link
* #setSignatureAcceptedForPackage(String)}, and {@link #setPackageNotInstalled(String)}.
* Once the policy has been set to this value it cannot be changed to any of the other policies.
*/
public static final int POLICY_CUSTOM = 3;
@IntDef(value = {
POLICY_SIGNATURE_ACCEPTED_FOR_DECLARED_PACKAGES,
POLICY_DENY_ALL,
POLICY_CUSTOM,
})
@Retention(RetentionPolicy.SOURCE)
@interface TestPolicy {
}
/**
* Returns a new {@link TestAppAuthenticatorBuilder} that can be used to create a new {@link
* AppAuthenticator} configured to behave as required for the test.
*
* @param context the context within which to create the {@link AppAuthenticator}
* @param xmlResource the ID of the XML resource containing the definitions for the
* permissions and expected identities based on package / expected signing
* certificate digests
* @return this instance of the {@code TestAppAuthenticatorBuilder}
*/
// This is not a setter for the builder but instead a static factory method to obtain a new
// builder.
@SuppressLint("BuilderSetStyle")
@NonNull
public static TestAppAuthenticatorBuilder createFromResource(@NonNull Context context,
@XmlRes int xmlResource) {
Resources resources = context.getResources();
XmlPullParser parser = resources.getXml(xmlResource);
return new TestAppAuthenticatorBuilder(context, parser);
}
/**
* Returns a new {@link TestAppAuthenticatorBuilder} that can be used to create a new {@link
* AppAuthenticator} configured to behave as required for the test.
*
* @param context the context within which to create the {@link AppAuthenticator}
* @param xmlInputStream the XML {@link InputStream} containing the definitions for the
* permissions and expected identities based on packages / expected
* signing certificate digests
* @return this instance of the {@code TestAppAuthenticatorBuilder}
*/
// This is not a setter for the builder but instead a static factory method to obtain a new
// builder.
@SuppressLint("BuilderSetStyle")
@NonNull
public static TestAppAuthenticatorBuilder createFromInputStream(
@NonNull Context context,
@NonNull InputStream xmlInputStream)
throws AppAuthenticatorXmlException {
XmlPullParser parser;
try {
parser = XmlPullParserFactory.newInstance().newPullParser();
parser.setInput(xmlInputStream, null);
} catch (XmlPullParserException e) {
throw new AppAuthenticatorXmlException("Unable to create parser from provided "
+ "InputStream", e);
}
return new TestAppAuthenticatorBuilder(context, parser);
}
/**
* Sets the policy to be used by the {@link AppAuthenticator} for the test.
*
* @param testPolicy the test policy to be used by the {@code AppAuthenticator{}
* @return this instance of the {@code TestAppAuthenticatorBuilder}
* @see #POLICY_SIGNATURE_ACCEPTED_FOR_DECLARED_PACKAGES
* @see #POLICY_DENY_ALL
* @see #POLICY_CUSTOM
*/
// The builder allows configuring other options that are not directly controlled by the
// AppAuthenticator.
@SuppressLint("MissingGetterMatchingBuilder")
public @NonNull TestAppAuthenticatorBuilder setTestPolicy(@TestPolicy int testPolicy) {
mTestPolicy = testPolicy;
return this;
}
/**
* Configures the resulting {@link AppAuthenticator} to always return that the signing
* identity matches the expected value when the specified {@code packageName} is queried.
*
* <p>Note, the specified {@code packageName} must be defined either explicitly via a
* {@code package} element or implicitly via a {@code all-packages} element; this ensures
* that the XML configuration is correct and that the specified package could be verified
* on device.
*
* @param packageName the name of the package for which the signing identity should be
* treated as matching the expected value
* @return this instance of the {@code TestAppAuthenticatorBuilder}
*/
// The builder allows configuring other options that are not directly controlled by the
// AppAuthenticator.
@SuppressLint("MissingGetterMatchingBuilder")
@NonNull
public TestAppAuthenticatorBuilder setSignatureAcceptedForPackage(
@NonNull String packageName) {
mTestPolicy = POLICY_CUSTOM;
mAppSignatureVerifierBuilder.setSignatureAcceptedForPackage(packageName);
return this;
}
/**
* Sets the provided {@code certDigest} as the signing identity for the specified {@code
* packageName}.
*
* @param packageName the name of the package that will use the provided signing identity
* @param certDigest the digest to be treated as the signing identity of the specified package
* @return this instance of the {@code TestAppAuthenticatorBuilder}
*/
// The builder allows configuring other options that are not directly controlled by the
// AppAuthenticator.
@SuppressLint("MissingGetterMatchingBuilder")
@NonNull
public TestAppAuthenticatorBuilder setSigningIdentityForPackage(
@NonNull String packageName,
@NonNull String certDigest) {
mTestPolicy = POLICY_CUSTOM;
mAppSignatureVerifierBuilder.setSigningIdentityForPackage(packageName,
AppAuthenticator.normalizeCertDigest(certDigest))
;
return this;
}
/**
* Sets the provided {@code uid} as the UID of the specified {@code packageName}.
*
* <p>This method can be used to verify the scenario where a calling package does not have the
* expected calling UID.
*
* @param packageName the name of the package that will be treated as having the provided uid
* @param uid the uid to use for the specified package
* @return this instance of the {@code TestAppAuthenticatorBuilder}
*/
// The builder allows configuring other options that are not directly controlled by the
// AppAuthenticator.
@SuppressLint("MissingGetterMatchingBuilder")
@NonNull
public TestAppAuthenticatorBuilder setUidForPackage(@NonNull String packageName,
int uid) {
mAppAuthenticatorUtilsBuilder.setUidForPackage(packageName, uid);
return this;
}
/**
* Treats the provided {@code packageName} as not being installed by the resulting {@link
* AppAuthenticator}.
*
* @param packageName the name of the package to be treated as not installed
* @return this instance of the {@code TestAppAuthenticatorBuilder}
*/
// The builder allows configuring other options that are not directly controlled by the
// AppAuthenticator.
@SuppressLint("MissingGetterMatchingBuilder")
@NonNull
public TestAppAuthenticatorBuilder setPackageNotInstalled(
@NonNull String packageName) {
mTestPolicy = POLICY_CUSTOM;
mAppAuthenticatorUtilsBuilder.setPackageNotInstalled(packageName);
mAppSignatureVerifierBuilder.setPackageNotInstalled(packageName);
return this;
}
/**
* Builds an {@link AppAuthenticator} with the specified config that can be injected to satisfy
* test requirements.
*
* @return a new {@code AppAuthenticator} that will respond to queries as configured
* @throws AppAuthenticatorXmlException if the provided XML config file is not in the proper
* format to create a new {@code AppAuthenticator}
* @throws IOException if an IO error is encountered when attempting to read
* the XML config file
*/
// This class is provided so that apps can inject a configurable AppAuthenticator for their
// tests, so it needs access to the restricted test APIs.
@SuppressLint("RestrictedApi")
@NonNull
public AppAuthenticator build() throws AppAuthenticatorXmlException, IOException {
// Obtain the config from the AppAuthenticator class to ensure that the provided XML is
// properly configured.
AppAuthenticator.AppAuthenticatorConfig config =
AppAuthenticator.createConfigFromParser(mParser);
// Configure the AppSignatureVerifier that will by the test AppAuthenticator.
mAppSignatureVerifierBuilder.setPermissionAllowMap(config.getPermissionAllowMap());
mAppSignatureVerifierBuilder.setExpectedIdentities(config.getExpectedIdentities());
mAppSignatureVerifierBuilder.setTestPolicy(mTestPolicy);
// Inject the AppSignatureVerifier and AppAuthenticatorUtils into the AppAuthenticator
// to configure it to behave as requested.
AppAuthenticator appAuthenticator = AppAuthenticator.createFromConfig(mContext, config);
appAuthenticator.setAppSignatureVerifier(mAppSignatureVerifierBuilder.build());
appAuthenticator.setAppAuthenticatorUtils(mAppAuthenticatorUtilsBuilder.build());
return appAuthenticator;
}
}