Domain Args
Manages an Amazon OpenSearch Domain.
Elasticsearch vs. OpenSearch
Amazon OpenSearch Service is the successor to Amazon Elasticsearch Service and supports OpenSearch and legacy Elasticsearch OSS (up to 7.10, the final open source version of the software). OpenSearch Domain configurations are similar in many ways to Elasticsearch Domain configurations. However, there are important differences including these:
OpenSearch has
engine_version
while Elasticsearch haselasticsearch_version
Versions are specified differently - e.g.,
Elasticsearch_7.10
with OpenSearch vs.7.10
for Elasticsearch.instance_type
argument values end insearch
for OpenSearch vs.elasticsearch
for Elasticsearch (e.g.,t2.micro.search
vs.t2.micro.elasticsearch
).The AWS-managed service-linked role for OpenSearch is called
AWSServiceRoleForAmazonOpenSearchService
instead ofAWSServiceRoleForAmazonElasticsearchService
for Elasticsearch. There are also some potentially unexpected similarities in configurations:ARNs for both are prefaced with
arn:aws:es:
.Both OpenSearch and Elasticsearch use assume role policies that refer to the
Principal
Service
ases.amazonaws.com
.IAM policy actions, such as those you will find in
access_policies
, are prefaced withes:
for both.
Example Usage
Basic Usage
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.opensearch.Domain;
import com.pulumi.aws.opensearch.DomainArgs;
import com.pulumi.aws.opensearch.inputs.DomainClusterConfigArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var example = new Domain("example", DomainArgs.builder()
.clusterConfig(DomainClusterConfigArgs.builder()
.instanceType("r4.large.search")
.build())
.engineVersion("Elasticsearch_7.10")
.tags(Map.of("Domain", "TestDomain"))
.build());
}
}
Access Policy
See also:
aws.opensearch.DomainPolicy
resource
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.AwsFunctions;
import com.pulumi.aws.inputs.GetRegionArgs;
import com.pulumi.aws.iam.IamFunctions;
import com.pulumi.aws.iam.inputs.GetPolicyDocumentArgs;
import com.pulumi.aws.opensearch.Domain;
import com.pulumi.aws.opensearch.DomainArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
final var config = ctx.config();
final var domain = config.get("domain").orElse("tf-test");
final var currentRegion = AwsFunctions.getRegion();
final var currentCallerIdentity = AwsFunctions.getCallerIdentity();
final var examplePolicyDocument = IamFunctions.getPolicyDocument(GetPolicyDocumentArgs.builder()
.statements(GetPolicyDocumentStatementArgs.builder()
.effect("Allow")
.principals(GetPolicyDocumentStatementPrincipalArgs.builder()
.type("*")
.identifiers("*")
.build())
.actions("es:*")
.resources(String.format("arn:aws:es:%s:%s:domain/%s/*", currentRegion.applyValue(getRegionResult -> getRegionResult.name()),currentCallerIdentity.applyValue(getCallerIdentityResult -> getCallerIdentityResult.accountId()),domain))
.conditions(GetPolicyDocumentStatementConditionArgs.builder()
.test("IpAddress")
.variable("aws:SourceIp")
.values("66.193.100.22/32")
.build())
.build())
.build());
var exampleDomain = new Domain("exampleDomain", DomainArgs.builder()
.accessPolicies(examplePolicyDocument.applyValue(getPolicyDocumentResult -> getPolicyDocumentResult.json()))
.build());
}
}
Log publishing to CloudWatch Logs
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.cloudwatch.LogGroup;
import com.pulumi.aws.iam.IamFunctions;
import com.pulumi.aws.iam.inputs.GetPolicyDocumentArgs;
import com.pulumi.aws.cloudwatch.LogResourcePolicy;
import com.pulumi.aws.cloudwatch.LogResourcePolicyArgs;
import com.pulumi.aws.opensearch.Domain;
import com.pulumi.aws.opensearch.DomainArgs;
import com.pulumi.aws.opensearch.inputs.DomainLogPublishingOptionArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var exampleLogGroup = new LogGroup("exampleLogGroup");
final var examplePolicyDocument = IamFunctions.getPolicyDocument(GetPolicyDocumentArgs.builder()
.statements(GetPolicyDocumentStatementArgs.builder()
.effect("Allow")
.principals(GetPolicyDocumentStatementPrincipalArgs.builder()
.type("Service")
.identifiers("es.amazonaws.com")
.build())
.actions(
"logs:PutLogEvents",
"logs:PutLogEventsBatch",
"logs:CreateLogStream")
.resources("arn:aws:logs:*")
.build())
.build());
var exampleLogResourcePolicy = new LogResourcePolicy("exampleLogResourcePolicy", LogResourcePolicyArgs.builder()
.policyName("example")
.policyDocument(examplePolicyDocument.applyValue(getPolicyDocumentResult -> getPolicyDocumentResult.json()))
.build());
var exampleDomain = new Domain("exampleDomain", DomainArgs.builder()
.logPublishingOptions(DomainLogPublishingOptionArgs.builder()
.cloudwatchLogGroupArn(exampleLogGroup.arn())
.logType("INDEX_SLOW_LOGS")
.build())
.build());
}
}
VPC based OpenSearch
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.ec2.Ec2Functions;
import com.pulumi.aws.ec2.inputs.GetVpcArgs;
import com.pulumi.aws.ec2.inputs.GetSubnetIdsArgs;
import com.pulumi.aws.AwsFunctions;
import com.pulumi.aws.inputs.GetRegionArgs;
import com.pulumi.aws.ec2.SecurityGroup;
import com.pulumi.aws.ec2.SecurityGroupArgs;
import com.pulumi.aws.ec2.inputs.SecurityGroupIngressArgs;
import com.pulumi.aws.iam.ServiceLinkedRole;
import com.pulumi.aws.iam.ServiceLinkedRoleArgs;
import com.pulumi.aws.iam.IamFunctions;
import com.pulumi.aws.iam.inputs.GetPolicyDocumentArgs;
import com.pulumi.aws.opensearch.Domain;
import com.pulumi.aws.opensearch.DomainArgs;
import com.pulumi.aws.opensearch.inputs.DomainClusterConfigArgs;
import com.pulumi.aws.opensearch.inputs.DomainVpcOptionsArgs;
import com.pulumi.resources.CustomResourceOptions;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
final var config = ctx.config();
final var vpc = config.get("vpc");
final var domain = config.get("domain").orElse("tf-test");
final var exampleVpc = Ec2Functions.getVpc(GetVpcArgs.builder()
.tags(Map.of("Name", vpc))
.build());
final var exampleSubnetIds = Ec2Functions.getSubnetIds(GetSubnetIdsArgs.builder()
.vpcId(exampleVpc.applyValue(getVpcResult -> getVpcResult.id()))
.tags(Map.of("Tier", "private"))
.build());
final var currentRegion = AwsFunctions.getRegion();
final var currentCallerIdentity = AwsFunctions.getCallerIdentity();
var exampleSecurityGroup = new SecurityGroup("exampleSecurityGroup", SecurityGroupArgs.builder()
.description("Managed by Pulumi")
.vpcId(exampleVpc.applyValue(getVpcResult -> getVpcResult.id()))
.ingress(SecurityGroupIngressArgs.builder()
.fromPort(443)
.toPort(443)
.protocol("tcp")
.cidrBlocks(exampleVpc.applyValue(getVpcResult -> getVpcResult.cidrBlock()))
.build())
.build());
var exampleServiceLinkedRole = new ServiceLinkedRole("exampleServiceLinkedRole", ServiceLinkedRoleArgs.builder()
.awsServiceName("opensearchservice.amazonaws.com")
.build());
final var examplePolicyDocument = IamFunctions.getPolicyDocument(GetPolicyDocumentArgs.builder()
.statements(GetPolicyDocumentStatementArgs.builder()
.effect("Allow")
.principals(GetPolicyDocumentStatementPrincipalArgs.builder()
.type("*")
.identifiers("*")
.build())
.actions("es:*")
.resources(String.format("arn:aws:es:%s:%s:domain/%s/*", currentRegion.applyValue(getRegionResult -> getRegionResult.name()),currentCallerIdentity.applyValue(getCallerIdentityResult -> getCallerIdentityResult.accountId()),domain))
.build())
.build());
var exampleDomain = new Domain("exampleDomain", DomainArgs.builder()
.engineVersion("OpenSearch_1.0")
.clusterConfig(DomainClusterConfigArgs.builder()
.instanceType("m4.large.search")
.zoneAwarenessEnabled(true)
.build())
.vpcOptions(DomainVpcOptionsArgs.builder()
.subnetIds(
exampleSubnetIds.applyValue(getSubnetIdsResult -> getSubnetIdsResult.ids()[0]),
exampleSubnetIds.applyValue(getSubnetIdsResult -> getSubnetIdsResult.ids()[1]))
.securityGroupIds(exampleSecurityGroup.id())
.build())
.advancedOptions(Map.of("rest.action.multi.allow_explicit_index", "true"))
.accessPolicies(examplePolicyDocument.applyValue(getPolicyDocumentResult -> getPolicyDocumentResult.json()))
.tags(Map.of("Domain", "TestDomain"))
.build(), CustomResourceOptions.builder()
.dependsOn(exampleServiceLinkedRole)
.build());
}
}
First apply
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.opensearch.Domain;
import com.pulumi.aws.opensearch.DomainArgs;
import com.pulumi.aws.opensearch.inputs.DomainAdvancedSecurityOptionsArgs;
import com.pulumi.aws.opensearch.inputs.DomainAdvancedSecurityOptionsMasterUserOptionsArgs;
import com.pulumi.aws.opensearch.inputs.DomainClusterConfigArgs;
import com.pulumi.aws.opensearch.inputs.DomainDomainEndpointOptionsArgs;
import com.pulumi.aws.opensearch.inputs.DomainEbsOptionsArgs;
import com.pulumi.aws.opensearch.inputs.DomainEncryptAtRestArgs;
import com.pulumi.aws.opensearch.inputs.DomainNodeToNodeEncryptionArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var example = new Domain("example", DomainArgs.builder()
.advancedSecurityOptions(DomainAdvancedSecurityOptionsArgs.builder()
.anonymousAuthEnabled(true)
.enabled(false)
.internalUserDatabaseEnabled(true)
.masterUserOptions(DomainAdvancedSecurityOptionsMasterUserOptionsArgs.builder()
.masterUserName("example")
.masterUserPassword("Barbarbarbar1!")
.build())
.build())
.clusterConfig(DomainClusterConfigArgs.builder()
.instanceType("r5.large.search")
.build())
.domainEndpointOptions(DomainDomainEndpointOptionsArgs.builder()
.enforceHttps(true)
.tlsSecurityPolicy("Policy-Min-TLS-1-2-2019-07")
.build())
.ebsOptions(DomainEbsOptionsArgs.builder()
.ebsEnabled(true)
.volumeSize(10)
.build())
.encryptAtRest(DomainEncryptAtRestArgs.builder()
.enabled(true)
.build())
.engineVersion("Elasticsearch_7.1")
.nodeToNodeEncryption(DomainNodeToNodeEncryptionArgs.builder()
.enabled(true)
.build())
.build());
}
}
Second apply
Notice that the only change is advanced_security_options.0.enabled
is now set to true
.
package generated_program;
import com.pulumi.Context;
import com.pulumi.Pulumi;
import com.pulumi.core.Output;
import com.pulumi.aws.opensearch.Domain;
import com.pulumi.aws.opensearch.DomainArgs;
import com.pulumi.aws.opensearch.inputs.DomainAdvancedSecurityOptionsArgs;
import com.pulumi.aws.opensearch.inputs.DomainAdvancedSecurityOptionsMasterUserOptionsArgs;
import com.pulumi.aws.opensearch.inputs.DomainClusterConfigArgs;
import com.pulumi.aws.opensearch.inputs.DomainDomainEndpointOptionsArgs;
import com.pulumi.aws.opensearch.inputs.DomainEbsOptionsArgs;
import com.pulumi.aws.opensearch.inputs.DomainEncryptAtRestArgs;
import com.pulumi.aws.opensearch.inputs.DomainNodeToNodeEncryptionArgs;
import java.util.List;
import java.util.ArrayList;
import java.util.Map;
import java.io.File;
import java.nio.file.Files;
import java.nio.file.Paths;
public class App {
public static void main(String[] args) {
Pulumi.run(App::stack);
}
public static void stack(Context ctx) {
var example = new Domain("example", DomainArgs.builder()
.advancedSecurityOptions(DomainAdvancedSecurityOptionsArgs.builder()
.anonymousAuthEnabled(true)
.enabled(true)
.internalUserDatabaseEnabled(true)
.masterUserOptions(DomainAdvancedSecurityOptionsMasterUserOptionsArgs.builder()
.masterUserName("example")
.masterUserPassword("Barbarbarbar1!")
.build())
.build())
.clusterConfig(DomainClusterConfigArgs.builder()
.instanceType("r5.large.search")
.build())
.domainEndpointOptions(DomainDomainEndpointOptionsArgs.builder()
.enforceHttps(true)
.tlsSecurityPolicy("Policy-Min-TLS-1-2-2019-07")
.build())
.ebsOptions(DomainEbsOptionsArgs.builder()
.ebsEnabled(true)
.volumeSize(10)
.build())
.encryptAtRest(DomainEncryptAtRestArgs.builder()
.enabled(true)
.build())
.engineVersion("Elasticsearch_7.1")
.nodeToNodeEncryption(DomainNodeToNodeEncryptionArgs.builder()
.enabled(true)
.build())
.build());
}
}
Import
OpenSearch domains can be imported using the domain_name
, e.g.,
$ pulumi import aws:opensearch/domain:Domain example domain_name
Constructors
Functions
Properties
Configuration block for fine-grained access control. Detailed below.
Configuration block for EBS related options, may be required based on chosen instance size. Detailed below.
Configuration block for encrypt at rest options. Only available for certain instance types. Detailed below.
Either Elasticsearch_X.Y
or OpenSearch_X.Y
to specify the engine version for the Amazon OpenSearch Service domain. For example, OpenSearch_1.0
or Elasticsearch_7.9
. See Creating and managing Amazon OpenSearch Service domains. Defaults to OpenSearch_1.1
.
Configuration block for VPC related options. Adding or removing this configuration forces a new resource (documentation). Detailed below. //