I am developing kafka trigger based azure functions in JAVA where the function uses below configuration for connection:
#KafkaTrigger(name = "kafkatrigger", topic = "kafka.topic", brokerList = "%BrokerList%",
consumerGroup = "default-consumer", protocol = BrokerProtocol.SSL,
sslCertificateLocation = "%sslCertificateLocation%", sslCaLocation = "%sslCaLocation%",
sslKeyLocation = "%sslKeyLocation%", sslKeyPassword = "%keyStorePassword%",
cardinality = Cardinality.ONE, dataType = "string")
So, In above configuration I do not want to upload the client private key, client public key and ca certificate through artifact on the container for security purpose. So, I want to keep the certificates at secure location like key vault, secret management and use their reference location in #KafkaTrigger annotation. How can I achieve that?
Related
I can get a link by those code, and it could download a file successfully.
BlobContainerSasPermission blobContainerSasPermission = new BlobContainerSasPermission()
.setReadPermission(true)
.setWritePermission(true)
.setListPermission(true);
BlobServiceSasSignatureValues builder = new BlobServiceSasSignatureValues(OffsetDateTime.now().plusDays(1), blobContainerSasPermission)
.setProtocol(SasProtocol.HTTPS_ONLY);
BlobClient client = new BlobClientBuilder()
.connectionString("connection string")
.blobName("")
.buildClient();
String blobContainerName = "test";
return String.format("https://%s.blob.core.windows.net/%s?%s",client.getAccountName(), blobContainerName, client.generateSas(builder));
but everyone could download the file by this link, I want the file could be downloaded by the one who is authorized. Is there any code or azure's setting(such as AD?) could implement this? Thanks
-------------------------update------------------------
I find a doc,and there gives a reason.
Note: This method call is only valid when using TokenCredential in this object's HttpPipeline.
but there is only BasicAuthenticationCredential which implements TokenCredential in my imported package. This is my mvn.
<dependency>
<groupId>com.azure</groupId>
<artifactId>azure-storage-blob</artifactId>
<version>12.11.0-beta.2</version>
</dependency>
And I tried this
String userName = "userName";
String password = "password";
BasicAuthenticationCredential basicAuthenticationCredential = new BasicAuthenticationCredential(userName,password);
BlobServiceClient blobServiceClient = new BlobServiceClientBuilder().endpoint(endpoint).credential(basicAuthenticationCredential).buildClient();
then I got this Status code 401, (InvalidAuthenticationInfo)
Gods, help me!
A SAS token for access to a container, directory, or blob may be
secured by using either Azure AD credentials or an account key. A SAS
secured with Azure AD credentials is called a user delegation SAS.
Microsoft recommends that you use Azure AD credentials when possible
as a security best practice, rather than using the account key, which
can be more easily compromised. When your application design requires
shared access signatures, use Azure AD credentials to create a user
delegation SAS for superior security.
Generating SAS query parameters with UserDelegationKey
The following sample generates SAS query parameters for an Azure storage container.
BlobSasPermission blobPermission = new BlobSasPermission()
.setReadPermission(true)
.setWritePermission(true);
// We are creating a SAS to a container because only container name is set.
BlobServiceSasSignatureValues builder = new BlobServiceSasSignatureValues()
.setProtocol(SasProtocol.HTTPS_ONLY) // Users MUST use HTTPS (not HTTP).
.setExpiryTime(OffsetDateTime.now().plusDays(2))
.setContainerName("my-container")
.setPermissions(blobPermission);
// Get a user delegation key after signing in with Azure AD
UserDelegationKey credential = new UserDelegationKey();
String account = "my-blob-storage-account";
BlobServiceSasQueryParameters sasQueryParameters = builder.generateSasQueryParameters(credential, account);
Check out Create a user delegation SAS and this for implementation details.
It looks like there is no way to implement this.
This is the answer.
This current code is giving me the error error:java.net.ConnectException:Connection refused:connect
AppServiceMSICredentials msiCredentials = new AppServiceMSICredentials(AzureEnvironment.AZURE,msiEndpoint, msiSecret);
keyVaultClient = new KeyVaultClient(msiCredentials);
SecretBundle secretBundle = keyVaultClient.getSecret(keyvault url, secretName);
I test the sample in my local, and face the same error. But I can't find detailed information if AppServiceMSICredentials supports access key vault locally.
You could try the official tutorial using a managed identity to connect Key Vault to an Azure Spring Cloud app.
The tutorial is based on Azure Identity library, and you could learn more about it with Java: https://learn.microsoft.com/en-us/azure/developer/java/sdk/identity-azure-hosted-auth.
private void getSecretWithManagedIdentity() {
ManagedIdentityCredential managedIdentityCredential = new ManagedIdentityCredentialBuilder()
.maxRetry(1)
.retryTimeout(duration -> Duration.ofMinutes(1))
.build();
secretClient = new SecretClientBuilder()
.vaultUrl(keyVaultUrl)
.credential(managedIdentityCredential)
.buildClient();
KeyVaultSecret secret = secretClient.getSecret(secret-name);
}
My application acts as an SAML IdP. For this, I am in the process of registering Service Providers with my application. For this, I connect to the SP Federation Metadata URL and download the XML.
Question is- is there any readily available java library which performs this tasks? Or do I need to extract the details manually using standard DOM APIs?
Note: My application maintains the user repository and their authentication and authorization details such as credentials, roles, operations, etc.
Hence can not really depend on third party IdPs such as ADFS or OneLogin.
Any help is much appreciated.
Thanks to codebrane for the pointers. I've figured out the way using opensaml libraries.
private void init(String metadata) throws Exception {
// parse metadata XML
EntityDescriptorImpl entityDescriptor = parseMetaData(metadata);
SPSSODescriptor spssoDescriptor = entityDescriptor.getSPSSODescriptor(SAMLConstants.SAML20P_NS);
// get signing/encryption certificates
List<KeyDescriptor> keyDescriptors = spssoDescriptor.getKeyDescriptors();
for (KeyDescriptor keyDescriptor: keyDescriptors) {
KeyInfo keyInfo = keyDescriptor.getKeyInfo();
X509Certificate samlCertificate = keyInfo.getX509Datas().get(0).getX509Certificates().get(0);
sigVerificationCertificate = KeyInfoSupport.getCertificate(samlCertificate);
}
// get SAML endpoints
assertionConsumerServices = spssoDescriptor.getAssertionConsumerServices();
singleLogoutServices = spssoDescriptor.getSingleLogoutServices();
// TODO - extract organization name etc.
}
I am writing an Android application to connect a sensor to an AWS IoT service.
I have been provided with the X.509 certificate, a pair of public-private key, clientEndpoint, etc.
I am trying to follow the AWS's Sample code (see here).
The instructions are clear, but I don't want to generate the certificate and the keys (I already have them).
Below is the code snippet:
// Create a new private key and certificate. This call
// creates both on the server and returns them to the
// device.
CreateKeysAndCertificateRequest createKeysAndCertificateRequest = new CreateKeysAndCertificateRequest();
createKeysAndCertificateRequest.setSetAsActive(true);
final CreateKeysAndCertificateResult createKeysAndCertificateResult;
createKeysAndCertificateResult = mIotAndroidClient.createKeysAndCertificate(createKeysAndCertificateRequest);
Log.i(LOG_TAG,"Cert ID: " +createKeysAndCertificateResult.getCertificateId() +" created.");
// store in keystore for use in MQTT client
// saved as alias "default" so a new certificate isn't
// generated each run of this application
AWSIotKeystoreHelper.saveCertificateAndPrivateKey(certificateId,createKeysAndCertificateResult.getCertificatePem(),createKeysAndCertificateResult.getKeyPair().getPrivateKey(),
keystorePath, keystoreName, keystorePassword);
// load keystore from file into memory to pass on
// connection
clientKeyStore = AWSIotKeystoreHelper.getIotKeystore(certificateId,keystorePath, keystoreName, keystorePassword);
How can I use the existing certificates files instead of generating new certificate and keys?
Thank you
Here's a full snip that I've successfully used with some test code.
String tempFilePath = context.getFilesDir().getAbsolutePath();
if (!AWSIotKeystoreHelper.isKeystorePresent(tempFilePath, "iotkeystore")) {
Resources resources = context.getResources();
int certId = resources.getIdentifier("foo_device_cert", "raw", context.getPackageName());
int privkeyId = resources.getIdentifier("foo_device_private_key", "raw", context.getPackageName());
String cert = TestUtils.loadTestResource(context, certId);
String privKey = TestUtils.loadTestResource(context, privkeyId);
AWSIotKeystoreHelper.saveCertificateAndPrivateKey("iotcert", cert, privKey, tempFilePath, "iotkeystore", "iotpasswd");
}
KeyStore keystore = AWSIotKeystoreHelper.getIotKeystore("iotcert", tempFilePath, "iotkeystore", "iotpasswd");
AWSIotMqttManager mqttManager = new AWSIotMqttManager("sdk-java", "xxxxxxxxxxxx-ats.iot.us-east-2.amazonaws.com");
mqttManager.connect(keystore, new LocalMqttStatusCallback());
mqttManager.subscribeToTopic("sdk/test/java", AWSIotMqttQos.QOS0, new LocalMessageCallback());
logger.info("testLoadCertificate()...");
In this case, I simply saved the certificates in the res/raw folder and loaded them at run time as shown above. This prob. isn't the best from a security standpoint, but should help you get something working. I put this entire snip into a Robolectric test case and the keystore gets reloaded each time. It properly connects and receives messages though.
The AWS documentation is really poor here, I wasn't able to find any working sample code from them (bad links) and I'm not wanting to just turn over my entire project to Amplify and it's automatic reconfiguration.
Good luck.
Use
AWSIotKeystoreHelper.isKeystorePresent(mKeystorePath, mKeystoreName) to check if keystore is already on you device
Check Alias using AWSIotKeystoreHelper.keystoreContainsAlias(mCertificateId, mKeystorePath, mKeystorePassword)
Get keystore using keystore = AWSIotKeystoreHelper.getIotKeystore(mCertificateId, mKeystoreName, mKeystorePassword)
Use keystore on mqttManager to connect
Summary
I need to establish a two-way SSL connection (with client certificate) in Android, preferrably using Apache HttpClient. I have access to the client's certificate, but no direct access to the clients private key. I can, however sign data with the client's private key.
Since I can't create a normal keystore without the private key, is there some way to override the SSL handshake and manually sign the challenge sent by the server?
What? You have no key, but you can still use it to sign?
The user's private key is stored on a dedicated hardware device. It will present the user's public certificate, and it allows me to pass in data that it will then sign/encrypt with the private key. But it will not give me the key itself.