/*
* Copyright Amazon.com, Inc. or its affiliates. All Rights Reserved.
*
* Licensed under the Apache License, Version 2.0 (the "License").
* You may not use this file except in compliance with the License.
* A copy of the License is located at
*
* http://aws.amazon.com/apache2.0
*
* or in the "license" file accompanying this file. This file 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.
*/
using Amazon.Runtime;
using Amazon.Runtime.Internal;
using Amazon.Runtime.Internal.Transform;
using Amazon.Runtime.Internal.Util;
using Amazon.Runtime.SharedInterfaces;
using Amazon.Runtime.SharedInterfaces.Internal;
using Amazon.S3.Internal;
using Amazon.S3.Model;
using Amazon.Util;
using System;
using System.Collections.Generic;
using System.Globalization;
namespace Amazon.S3.Encryption
{
///
/// This class extends the AmazonS3Client and provides client side encryption when reading or writing S3 objects.
///
[Obsolete("This feature is in maintenance mode, no new updates will be released. " +
"Please transition to https://www.nuget.org/packages/Amazon.Extensions.S3.Encryption " +
"and see https://docs.aws.amazon.com/general/latest/gr/aws_sdk_cryptography.html for more information.")]
public partial class AmazonS3EncryptionClient : AmazonS3Client, IAmazonS3Encryption
{
private static readonly string S3KMSEncryptionFeature = "the KMS encryption features of " + typeof(AmazonS3EncryptionClient).Name;
private ICoreAmazonKMS kmsClient;
private readonly object kmsClientLock = new object();
internal EncryptionMaterials EncryptionMaterials
{
get;
private set;
}
internal ICoreAmazonKMS KMSClient
{
get
{
if (kmsClient == null)
{
lock (kmsClientLock)
{
if (kmsClient == null)
kmsClient = new CoreAmazonKMS(this, S3KMSEncryptionFeature);
}
}
return kmsClient;
}
}
private AmazonS3Client s3ClientForInstructionFile;
internal AmazonS3Client S3ClientForInstructionFile
{
get
{
if (s3ClientForInstructionFile == null)
{
s3ClientForInstructionFile = new AmazonS3Client(Credentials, S3CryptoConfig);
}
return s3ClientForInstructionFile;
}
}
internal AmazonS3CryptoConfiguration S3CryptoConfig
{
get;
private set;
}
internal Dictionary CurrentMultiPartUploadKeys = new Dictionary();
internal const string S3CryptoStream = "S3-Crypto-Stream";
#region Constructors
///
/// Constructs AmazonS3EncryptionClient with the Encryption materials and credentials loaded from the application's
/// default configuration, and if unsuccessful from the Instance Profile service on an EC2 instance.
///
/// Example App.config with credentials set.
///
/// <?xml version="1.0" encoding="utf-8" ?>
/// <configuration>
/// <appSettings>
/// <add key="AWSProfileName" value="AWS Default"/>
/// </appSettings>
/// </configuration>
///
///
///
///
/// The encryption materials to be used to encrypt and decrypt envelope key.
///
public AmazonS3EncryptionClient(EncryptionMaterials materials)
: base()
{
this.EncryptionMaterials = materials;
S3CryptoConfig = new AmazonS3CryptoConfiguration();
}
///
/// Constructs AmazonS3EncryptionClient with the Encryption materials and credentials loaded from the application's
/// default configuration, and if unsuccessful from the Instance Profile service on an EC2 instance.
///
/// Example App.config with credentials set.
///
/// <?xml version="1.0" encoding="utf-8" ?>
/// <configuration>
/// <appSettings>
/// <add key="AWSProfileName" value="AWS Default"/>
/// </appSettings>
/// </configuration>
///
///
///
///
/// The region to connect.
///
///
/// The encryption materials to be used to encrypt and decrypt envelope key.
///
public AmazonS3EncryptionClient(RegionEndpoint region, EncryptionMaterials materials)
: base(region)
{
this.EncryptionMaterials = materials;
S3CryptoConfig = new AmazonS3CryptoConfiguration();
}
///
/// Constructs AmazonS3EncryptionClient with the Encryption materials,
/// AmazonS3 CryptoConfiguration object and credentials loaded from the application's
/// default configuration, and if unsuccessful from the Instance Profile service on an EC2 instance.
///
/// Example App.config with credentials set.
///
/// <?xml version="1.0" encoding="utf-8" ?>
/// <configuration>
/// <appSettings>
/// <add key="AWSProfileName" value="AWS Default"/>
/// </appSettings>
/// </configuration>
///
///
///
///
/// The AmazonS3EncryptionClient CryptoConfiguration Object
///
///
/// The encryption materials to be used to encrypt and decrypt envelope key.
///
public AmazonS3EncryptionClient(AmazonS3CryptoConfiguration config, EncryptionMaterials materials)
: base(config)
{
this.EncryptionMaterials = materials;
S3CryptoConfig = config;
}
///
/// Constructs AmazonS3EncryptionClient with AWS Credentials and Encryption materials.
///
///
/// The encryption materials to be used to encrypt and decrypt envelope key.
///
/// AWS Credentials
public AmazonS3EncryptionClient(AWSCredentials credentials, EncryptionMaterials materials)
: base(credentials)
{
this.EncryptionMaterials = materials;
S3CryptoConfig = new AmazonS3CryptoConfiguration();
}
///
/// Constructs AmazonS3EncryptionClient with AWS Credentials, Region and Encryption materials
///
/// AWS Credentials
/// The region to connect.
///
/// The encryption materials to be used to encrypt and decrypt envelope key.
///
public AmazonS3EncryptionClient(AWSCredentials credentials, RegionEndpoint region, EncryptionMaterials materials)
: base(credentials, region)
{
this.EncryptionMaterials = materials;
S3CryptoConfig = new AmazonS3CryptoConfiguration();
}
///
/// Constructs AmazonS3EncryptionClient with AWS Credentials, AmazonS3CryptoConfiguration Configuration object
/// and Encryption materials
///
/// AWS Credentials
/// The AmazonS3EncryptionClient CryptoConfiguration Object
///
/// The encryption materials to be used to encrypt and decrypt envelope key.
///
public AmazonS3EncryptionClient(AWSCredentials credentials, AmazonS3CryptoConfiguration config, EncryptionMaterials materials)
: base(credentials, config)
{
this.EncryptionMaterials = materials;
S3CryptoConfig = config;
}
///
/// Constructs AmazonS3EncryptionClient with AWS Access Key ID,
/// AWS Secret Key and Encryption materials
///
/// AWS Access Key ID
/// AWS Secret Access Key
/// The encryption materials to be used to encrypt and decrypt envelope key.
public AmazonS3EncryptionClient(string awsAccessKeyId, string awsSecretAccessKey, EncryptionMaterials materials)
: base(awsAccessKeyId, awsSecretAccessKey)
{
this.EncryptionMaterials = materials;
S3CryptoConfig = new AmazonS3CryptoConfiguration();
}
///
/// Constructs AmazonS3EncryptionClient with AWS Access Key ID,
/// AWS Secret Key, Region and Encryption materials
///
/// AWS Access Key ID
/// AWS Secret Access Key
/// The region to connect.
/// The encryption materials to be used to encrypt and decrypt envelope key.
public AmazonS3EncryptionClient(string awsAccessKeyId, string awsSecretAccessKey, RegionEndpoint region, EncryptionMaterials materials)
: base(awsAccessKeyId, awsSecretAccessKey, region)
{
this.EncryptionMaterials = materials;
S3CryptoConfig = new AmazonS3CryptoConfiguration();
}
///
/// Constructs AmazonS3EncryptionClient with AWS Access Key ID, Secret Key,
/// AmazonS3 CryptoConfiguration object and Encryption materials.
///
/// AWS Access Key ID
/// AWS Secret Access Key
/// The AmazonS3EncryptionClient CryptoConfiguration Object
/// The encryption materials to be used to encrypt and decrypt envelope key.
public AmazonS3EncryptionClient(string awsAccessKeyId, string awsSecretAccessKey, AmazonS3CryptoConfiguration config, EncryptionMaterials materials)
: base(awsAccessKeyId, awsSecretAccessKey, config)
{
this.EncryptionMaterials = materials;
S3CryptoConfig = config;
}
///
/// Constructs AmazonS3EncryptionClient with AWS Access Key ID, Secret Key,
/// SessionToken and Encryption materials.
///
/// AWS Access Key ID
/// AWS Secret Access Key
/// AWS Session Token
///
/// The encryption materials to be used to encrypt and decrypt envelope key.
///
public AmazonS3EncryptionClient(string awsAccessKeyId, string awsSecretAccessKey, string awsSessionToken, EncryptionMaterials materials)
: base(awsAccessKeyId, awsSecretAccessKey, awsSessionToken)
{
this.EncryptionMaterials = materials;
S3CryptoConfig = new AmazonS3CryptoConfiguration();
}
///
/// Constructs AmazonS3EncryptionClient with AWS Access Key ID, Secret Key,
/// SessionToken, Region and Encryption materials.
///
/// AWS Access Key ID
/// AWS Secret Access Key
/// AWS Session Token
/// The region to connect.
/// The encryption materials to be used to encrypt and decrypt envelope key.
public AmazonS3EncryptionClient(string awsAccessKeyId, string awsSecretAccessKey, string awsSessionToken, RegionEndpoint region, EncryptionMaterials materials)
: base(awsAccessKeyId, awsSecretAccessKey, awsSessionToken, region)
{
this.EncryptionMaterials = materials;
S3CryptoConfig = new AmazonS3CryptoConfiguration();
}
///
/// Constructs AmazonS3EncryptionClient with AWS Access Key ID, Secret Key, SessionToken
/// AmazonS3EncryptionClient CryptoConfiguration object and Encryption materials.
///
/// AWS Access Key ID
/// AWS Secret Access Key
/// AWS Session Token
/// The AmazonS3EncryptionClient CryptoConfiguration Object
///
/// The encryption materials to be used to encrypt and decrypt envelope key.
///
public AmazonS3EncryptionClient(string awsAccessKeyId, string awsSecretAccessKey, string awsSessionToken, AmazonS3CryptoConfiguration config, EncryptionMaterials materials)
: base(awsAccessKeyId, awsSecretAccessKey, awsSessionToken, config)
{
this.EncryptionMaterials = materials;
S3CryptoConfig = config;
}
#endregion
///
/// Turn off response logging because it will interfere with decrypt of the data coming back from S3.
///
protected override bool SupportResponseLogging
{
get
{
return false;
}
}
///
/// Customize the pipeline to allow encryption.
///
///
protected override void CustomizeRuntimePipeline(RuntimePipeline pipeline)
{
base.CustomizeRuntimePipeline(pipeline);
pipeline.AddHandlerBefore(new Amazon.S3.Encryption.Internal.SetupEncryptionHandler(this));
pipeline.AddHandlerAfter(new Amazon.S3.Encryption.Internal.UserAgentHandler());
pipeline.AddHandlerBefore(new Amazon.S3.Encryption.Internal.SetupDecryptionHandler(this));
}
///
/// Dispose this instance
///
///
protected override void Dispose(bool disposing)
{
lock (kmsClientLock)
{
if (kmsClient != null)
{
kmsClient.Dispose();
kmsClient = null;
}
}
base.Dispose(disposing);
}
}
}