From c543683165926699d3a4c782815cacf689b1ad18 Mon Sep 17 00:00:00 2001 From: Shalev Avhar Date: Thu, 4 Sep 2025 17:46:23 +0300 Subject: [PATCH 01/16] feat: Add AWS Hosted by Port integration documentation - Introduced new JSON and Markdown files for the AWS Hosted by Port integration, detailing features, installation instructions, and examples. - Added support for multi-account configurations using AWS Organizations. - Included comprehensive examples for configuring various AWS resources and advanced use cases. - Documented prerequisites, installation processes, and troubleshooting steps for users. This integration is currently in beta and requires access through Port's Ocean platform. --- .../cloud-providers/aws-v3/_category_.json | 8 + .../cloud-providers/aws-v3/aws-v3.md | 346 ++++++++++ .../aws-v3/examples/_category_.json | 8 + .../aws-v3/examples/examples.md | 619 ++++++++++++++++++ .../aws-v3/installations/installation.md | 301 +++++++++ .../aws-v3/installations/multi_account.md | 316 +++++++++ 6 files changed, 1598 insertions(+) create mode 100644 docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/_category_.json create mode 100644 docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/aws-v3.md create mode 100644 docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/examples/_category_.json create mode 100644 docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/examples/examples.md create mode 100644 docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/installations/installation.md create mode 100644 docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/installations/multi_account.md diff --git a/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/_category_.json b/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/_category_.json new file mode 100644 index 0000000000..1011f113cd --- /dev/null +++ b/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/_category_.json @@ -0,0 +1,8 @@ +{ + "label": "AWS Hosted by Port", + "position": 3, + "link": { + "type": "generated-index", + "description": "AWS Hosted by Port integration documentation. Learn how to integrate your AWS resources with zero maintenance required - fully hosted and managed by Port." + } +} diff --git a/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/aws-v3.md b/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/aws-v3.md new file mode 100644 index 0000000000..955f8f7165 --- /dev/null +++ b/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/aws-v3.md @@ -0,0 +1,346 @@ +--- +sidebar_position: 3 +--- + +import Tabs from "@theme/Tabs"; +import TabItem from "@theme/TabItem"; +import Image from "@theme/IdealImage"; +import MetricsAndSyncStatus from "/docs/build-your-software-catalog/sync-data-to-catalog/templates/_metrics_and_sync_status.mdx" + +# AWS Hosted by Port + +:::warning Beta Feature +AWS Hosted by Port is currently in **beta mode** and is not yet available for all Port users. Contact your Port representative to request access to this integration. +::: + +Port's AWS Hosted by Port integration allows you to import your AWS resources into Port with **zero maintenance required**. The integration is fully hosted and managed by Port, providing a seamless experience for discovering and managing your AWS infrastructure. + +The integration periodically syncs your AWS resources to ensure your Port catalog stays up-to-date with your AWS infrastructure. + +:::tip +AWS Hosted by Port is fully managed by Port - no maintenance, updates, or infrastructure management required on your end. +::: + +## 💡 AWS Hosted by Port common use cases + +Easily fill your software catalog with data directly from your AWS Organization, for example: + +- Map all the resources in your AWS Accounts, including **ECS Clusters**, **S3 Buckets**, and **EC2 Instances** with zero maintenance required. +- Keep your Port catalog synchronized with your AWS infrastructure through periodic updates. +- Use relations to create complete, easily digestible views of your AWS infrastructure inside Port. +- Enjoy a fully managed experience with no infrastructure to maintain or updates to apply. + +## How it works + +AWS Hosted by Port connects to your AWS accounts using **OIDC (OpenID Connect)** authentication to securely access your AWS resources: + +### Single Account Setup +1. **Role Assumption**: The integration assumes the IAM role you create in your AWS account +2. **Resource Discovery**: It discovers and exports your AWS resources to Port +3. **Periodic Sync**: The integration periodically syncs to keep your Port catalog up-to-date + +### Multi-Account Setup +1. **Organization Access**: The integration connects to your AWS Organizations master account +2. **Account Discovery**: It lists all member accounts in your organization +3. **Cross-Account Access**: For each account, it assumes the appropriate IAM role +4. **Resource Export**: It exports resources from all accounts to Port +5. **Periodic Sync**: The integration periodically syncs across all accounts + +The integration currently supports the following AWS resource types: +- **S3 Buckets**: Complete bucket information including properties, tags, and metadata +- **ECS Clusters**: Cluster details, services, and task definitions +- **EC2 Instances**: Instance information, security groups, and networking details + +:::info More Resource Types Coming Soon +We're actively working on adding support for additional AWS resource types to provide comprehensive coverage of your AWS infrastructure. +::: + +## Key advantages over standard AWS integration + +AWS Hosted by Port provides several advantages over the standard AWS integration: + +- **Fully Hosted**: No infrastructure to maintain, update, or monitor +- **Simplified Installation**: Just deploy CloudFormation templates to create IAM roles +- **Complete Data**: Ensures no missing or incomplete resource information +- **Periodic Sync**: Regular updates to keep your catalog current +- **Zero Maintenance**: Port handles all updates, scaling, and infrastructure management + +## Getting started + +Continue to the [installation](./installations/installation.md) guide to learn how to install AWS Hosted by Port. + +## Multiple accounts support + +To properly configure permissions for production and to enable multiple accounts collection check out our [multiple accounts guide](./installations/multi_account.md) + +## Configuration + +Port integrations use a [YAML mapping block](/build-your-software-catalog/customize-integrations/configure-mapping#configuration-structure) to ingest data from the third-party api into Port. + +The mapping makes use of the [JQ JSON processor](https://stedolan.github.io/jq/manual/) to select, modify, concatenate, transform and perform other operations on existing fields and values from the integration API. + +### Default mapping configuration + +This is the default mapping configuration you get after installing AWS Hosted by Port. + +
+Default mapping configuration (Click to expand) + +```yaml showLineNumbers +resources: +- kind: AWS::Organizations::Account + selector: + query: 'true' + port: + entity: + mappings: + identifier: .Id + title: .Name + blueprint: '"awsAccount"' + properties: + arn: .Arn + email: .Email + status: .Status + joined_method: .JoinedMethod + joined_timestamp: .JoinedTimestamp | sub(" "; "T") +- kind: AWS::S3::Bucket + selector: + query: 'true' + useGetResourceAPI: 'true' + port: + entity: + mappings: + identifier: .Identifier + title: .Identifier + blueprint: '"cloudResource"' + properties: + kind: .__Kind + region: .Properties.RegionalDomainName | capture(".*\\.(?[^\\.]+)\\.amazonaws\\.com") + | .region + tags: .Properties.Tags + arn: .Properties.Arn + link: .Properties | select(.Arn != null) | "https://console.aws.amazon.com/go/view?arn=" + + .Arn + relations: + account: .__AccountId +- kind: AWS::EC2::Instance + selector: + query: 'true' + port: + entity: + mappings: + identifier: .Identifier + title: .Identifier + blueprint: '"cloudResource"' + properties: + kind: .__Kind + region: .__Region + tags: .Properties.Tags + arn: .Properties.Arn + link: .Properties | select(.Arn != null) | "https://console.aws.amazon.com/go/view?arn=" + + .Arn + relations: + account: .__AccountId +- kind: AWS::ECS::Cluster + selector: + query: 'true' + useGetResourceAPI: 'true' + port: + entity: + mappings: + identifier: .Properties.Arn + title: .Identifier + blueprint: '"cloudResource"' + properties: + kind: .__Kind + region: .__Region + tags: .Properties.Tags + arn: .Properties.Arn + link: .Properties | select(.Arn != null) | "https://console.aws.amazon.com/go/view?arn=" + + .Arn + relations: + account: .__AccountId +- kind: AWS::Lambda::Function + selector: + query: 'true' + useGetResourceAPI: 'true' + port: + entity: + mappings: + identifier: .Properties.FunctionName + title: .Properties.FunctionName + blueprint: '"cloudResource"' + properties: + kind: .__Kind + region: .__Region + runtime: .Properties.Runtime + memory_size: .Properties.MemorySize + timeout: .Properties.Timeout + tags: .Properties.Tags + arn: .Properties.Arn + link: .Properties | select(.Arn != null) | "https://console.aws.amazon.com/go/view?arn=" + + .Arn + relations: + account: .__AccountId +- kind: AWS::RDS::DBInstance + selector: + query: 'true' + useGetResourceAPI: 'true' + port: + entity: + mappings: + identifier: .Properties.DBInstanceIdentifier + title: .Properties.DBInstanceIdentifier + blueprint: '"cloudResource"' + properties: + kind: .__Kind + region: .__Region + engine: .Properties.Engine + engine_version: .Properties.EngineVersion + instance_class: .Properties.DBInstanceClass + tags: .Properties.Tags + arn: .Properties.Arn + link: .Properties | select(.Arn != null) | "https://console.aws.amazon.com/go/view?arn=" + + .Arn + relations: + account: .__AccountId +``` + +
+ + + +## Advanced Configuration + +### AWS SDK v3 Specific Features + +The AWS-v3 integration leverages several AWS SDK v3 specific features: + +- **Modular Architecture**: Only imports the specific AWS services you need, reducing bundle size +- **Enhanced TypeScript Support**: Full TypeScript support with better type inference +- **Improved Error Handling**: More granular error types and better error messages +- **Better Performance**: Optimized for performance with reduced memory footprint + +### Resource Discovery Optimization + +The AWS-v3 integration includes several optimizations for resource discovery: + +- **Parallel Processing**: Processes multiple regions and services in parallel +- **Smart Caching**: Implements intelligent caching to reduce API calls +- **Rate Limiting**: Built-in rate limiting to respect AWS API limits +- **Retry Logic**: Enhanced retry logic with exponential backoff + +### Configuration Examples + +#### Basic Configuration + +```yaml showLineNumbers +resources: +- kind: AWS::S3::Bucket + selector: + query: 'true' + useGetResourceAPI: 'true' + port: + entity: + mappings: + identifier: .Identifier + title: .Identifier + blueprint: '"s3Bucket"' + properties: + region: .Properties.RegionalDomainName | capture(".*\\.(?[^\\.]+)\\.amazonaws\\.com") | .region + tags: .Properties.Tags + arn: .Properties.Arn +``` + +#### Advanced Configuration with Relations + +```yaml showLineNumbers +resources: +- kind: AWS::ECS::Service + selector: + query: 'true' + useGetResourceAPI: 'true' + port: + entity: + mappings: + identifier: .Properties.ServiceArn + title: .Properties.ServiceName + blueprint: '"ecsService"' + properties: + cluster: .Properties.ClusterArn + desired_count: .Properties.DesiredCount + running_count: .Properties.RunningCount + tags: .Properties.Tags + arn: .Properties.ServiceArn + relations: + cluster: .Properties.ClusterArn + account: .__AccountId +``` + +## Troubleshooting + +### Common Issues + +#### AWS SDK v3 Compatibility + +If you encounter compatibility issues with AWS SDK v3: + +1. Ensure you're using the latest version of the AWS-v3 integration +2. Check that your AWS credentials are properly configured +3. Verify that the required AWS services are available in your region + +#### Performance Issues + +For performance optimization: + +1. Use the `useGetResourceAPI: 'true'` flag for resources that support it +2. Implement proper filtering in your selector queries +3. Consider using parallel processing for large-scale deployments + +#### Memory Usage + +To optimize memory usage: + +1. Use specific resource kinds instead of broad queries +2. Implement proper pagination for large datasets +3. Monitor memory usage and adjust configuration accordingly + +### Debug Mode + +Enable debug mode for detailed logging: + +```yaml showLineNumbers +debug: true +log_level: "DEBUG" +``` + +This will provide detailed information about: +- API calls being made +- Resource processing status +- Error details and stack traces +- Performance metrics + +## Migration from AWS Integration + +If you're migrating from the standard AWS integration to AWS-v3: + +1. **Backup Configuration**: Save your current configuration +2. **Update Mapping**: Review and update your mapping configuration if needed +3. **Test Integration**: Test the new integration in a development environment +4. **Deploy**: Deploy to production once testing is complete + +### Configuration Changes + +The main differences in configuration: + +- Enhanced error handling options +- Additional performance tuning parameters +- Improved resource discovery settings +- Better support for complex resource relationships + +## Support and Resources + +- **Documentation**: [AWS SDK v3 Documentation](https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/) +- **Community**: [Port Community Forum](https://github.com/port-labs/port/discussions) +- **Issues**: [Report Issues](https://github.com/port-labs/ocean/issues) +- **Source Code**: [AWS-v3 Integration](https://github.com/port-labs/ocean/tree/main/integrations/aws-v3) diff --git a/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/examples/_category_.json b/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/examples/_category_.json new file mode 100644 index 0000000000..b3a6656f62 --- /dev/null +++ b/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/examples/_category_.json @@ -0,0 +1,8 @@ +{ + "label": "Examples", + "position": 4, + "link": { + "type": "generated-index", + "description": "Comprehensive examples for configuring the AWS-v3 integration with various AWS services, filtering options, and advanced use cases." + } +} diff --git a/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/examples/examples.md b/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/examples/examples.md new file mode 100644 index 0000000000..b4723357e3 --- /dev/null +++ b/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/examples/examples.md @@ -0,0 +1,619 @@ +--- +sidebar_position: 4 +--- + +import Tabs from "@theme/Tabs"; +import TabItem from "@theme/TabItem"; + +# AWS Hosted by Port Examples + +This page provides comprehensive examples for configuring AWS Hosted by Port with the currently supported AWS services and use cases. + +## Currently Supported AWS Resources + +AWS Hosted by Port currently supports the following AWS resource types: + +- **S3 Buckets**: Complete bucket information including properties, tags, and metadata +- **ECS Clusters**: Cluster details, services, and task definitions +- **EC2 Instances**: Instance information, security groups, and networking details + +:::info More Resource Types Coming Soon +We're actively working on adding support for additional AWS resource types to provide comprehensive coverage of your AWS infrastructure. +::: + +## Basic Examples + +### S3 Buckets + +Map S3 buckets with detailed properties: + +```yaml showLineNumbers +resources: +- kind: AWS::S3::Bucket + selector: + query: 'true' + useGetResourceAPI: 'true' + port: + entity: + mappings: + - identifier: .Identifier + title: .Identifier + blueprint: '"s3Bucket"' + properties: + kind: .__Kind + region: .Properties.RegionalDomainName | capture(".*\\.(?[^\\.]+)\\.amazonaws\\.com") | .region + account_id: .__AccountId + creation_date: .Properties.CreationDate + tags: .Properties.Tags + arn: .Properties.Arn + link: .Properties | select(.Arn != null) | "https://console.aws.amazon.com/go/view?arn=" + .Arn + relations: + account: .__AccountId +``` + +### EC2 Instances + +Map EC2 instances with comprehensive details: + +```yaml showLineNumbers +resources: +- kind: AWS::EC2::Instance + selector: + query: 'true' + port: + entity: + mappings: + - identifier: .Identifier + title: .Identifier + blueprint: '"ec2Instance"' + properties: + kind: .__Kind + region: .__Region + account_id: .__AccountId + instance_type: .Properties.InstanceType + state: .Properties.State.Name + launch_time: .Properties.LaunchTime + public_ip: .Properties.PublicIpAddress + private_ip: .Properties.PrivateIpAddress + vpc_id: .Properties.VpcId + subnet_id: .Properties.SubnetId + security_groups: .Properties.SecurityGroups + tags: .Properties.Tags + arn: .Properties.Arn + link: .Properties | select(.Arn != null) | "https://console.aws.amazon.com/go/view?arn=" + .Arn + relations: + account: .__AccountId + vpc: .Properties.VpcId +``` + + +## Advanced Examples + +### ECS Clusters and Services + +Map ECS clusters and their services with relationships: + +```yaml showLineNumbers +resources: +# ECS Clusters +- kind: AWS::ECS::Cluster + selector: + query: 'true' + useGetResourceAPI: 'true' + port: + entity: + mappings: + - identifier: .Properties.ClusterArn + title: .Properties.ClusterName + blueprint: '"ecsCluster"' + properties: + kind: .__Kind + region: .__Region + account_id: .__AccountId + cluster_name: .Properties.ClusterName + status: .Properties.Status + running_tasks_count: .Properties.RunningTasksCount + pending_tasks_count: .Properties.PendingTasksCount + active_services_count: .Properties.ActiveServicesCount + capacity_providers: .Properties.CapacityProviders + tags: .Properties.Tags + arn: .Properties.ClusterArn + link: .Properties | select(.Arn != null) | "https://console.aws.amazon.com/go/view?arn=" + .Arn + relations: + account: .__AccountId + +# ECS Services +- kind: AWS::ECS::Service + selector: + query: 'true' + useGetResourceAPI: 'true' + port: + entity: + mappings: + - identifier: .Properties.ServiceArn + title: .Properties.ServiceName + blueprint: '"ecsService"' + properties: + kind: .__Kind + region: .__Region + account_id: .__AccountId + service_name: .Properties.ServiceName + cluster_arn: .Properties.ClusterArn + task_definition: .Properties.TaskDefinition + desired_count: .Properties.DesiredCount + running_count: .Properties.RunningCount + pending_count: .Properties.PendingCount + launch_type: .Properties.LaunchType + platform_version: .Properties.PlatformVersion + status: .Properties.Status + tags: .Properties.Tags + arn: .Properties.ServiceArn + link: .Properties | select(.Arn != null) | "https://console.aws.amazon.com/go/view?arn=" + .Arn + relations: + account: .__AccountId + cluster: .Properties.ClusterArn +``` + + +## Multi-Account Examples + +### Organization-Wide Resource Mapping + +Map resources across multiple accounts in an organization: + +```yaml showLineNumbers +resources: +# Organization Account +- kind: AWS::Organizations::Account + selector: + query: 'true' + port: + entity: + mappings: + - identifier: .Id + title: .Name + blueprint: '"awsAccount"' + properties: + arn: .Arn + email: .Email + status: .Status + joined_method: .JoinedMethod + joined_timestamp: .JoinedTimestamp | sub(" "; "T") + account_id: .Id + relations: + organization: .__OrganizationId + +# Cross-Account S3 Buckets +- kind: AWS::S3::Bucket + selector: + query: 'true' + useGetResourceAPI: 'true' + port: + entity: + mappings: + - identifier: .Identifier + title: .Identifier + blueprint: '"s3Bucket"' + properties: + kind: .__Kind + region: .Properties.RegionalDomainName | capture(".*\\.(?[^\\.]+)\\.amazonaws\\.com") | .region + account_id: .__AccountId + creation_date: .Properties.CreationDate + tags: .Properties.Tags + arn: .Properties.Arn + environment: .Properties.Tags.Environment // "unknown" + project: .Properties.Tags.Project // "unknown" + cost_center: .Properties.Tags.CostCenter // "unknown" + link: .Properties | select(.Arn != null) | "https://console.aws.amazon.com/go/view?arn=" + .Arn + relations: + account: .__AccountId +``` + +## Filtering Examples + +### Environment-Based Filtering + +Filter resources by environment tags: + +```yaml showLineNumbers +resources: +- kind: AWS::EC2::Instance + selector: + query: '.Properties.Tags | select(.Key == "Environment") | .Value == "production"' + port: + entity: + mappings: + - identifier: .Identifier + title: .Identifier + blueprint: '"ec2Instance"' + properties: + kind: .__Kind + region: .__Region + account_id: .__AccountId + instance_type: .Properties.InstanceType + state: .Properties.State.Name + environment: .Properties.Tags | select(.Key == "Environment") | .Value + project: .Properties.Tags | select(.Key == "Project") | .Value + tags: .Properties.Tags + arn: .Properties.Arn + relations: + account: .__AccountId + +- kind: AWS::S3::Bucket + selector: + query: '.Properties.Tags | select(.Key == "Environment") | .Value == "production"' + port: + entity: + mappings: + - identifier: .Identifier + title: .Identifier + blueprint: '"s3Bucket"' + properties: + kind: .__Kind + region: .Properties.RegionalDomainName | capture(".*\\.(?[^\\.]+)\\.amazonaws\\.com") | .region + account_id: .__AccountId + environment: .Properties.Tags | select(.Key == "Environment") | .Value + project: .Properties.Tags | select(.Key == "Project") | .Value + tags: .Properties.Tags + arn: .Properties.Arn + relations: + account: .__AccountId +``` + +### Resource Type Filtering + +Filter specific resource types: + +```yaml showLineNumbers +resources: +# Only t3.micro instances +- kind: AWS::EC2::Instance + selector: + query: '.Properties.InstanceType == "t3.micro"' + port: + entity: + mappings: + - identifier: .Identifier + title: .Identifier + blueprint: '"ec2Instance"' + properties: + kind: .__Kind + region: .__Region + account_id: .__AccountId + instance_type: .Properties.InstanceType + state: .Properties.State.Name + tags: .Properties.Tags + arn: .Properties.Arn + relations: + account: .__AccountId + +# Only t3.micro instances +- kind: AWS::EC2::Instance + selector: + query: '.Properties.InstanceType == "t3.micro"' + port: + entity: + mappings: + - identifier: .Identifier + title: .Identifier + blueprint: '"ec2Instance"' + properties: + kind: .__Kind + region: .__Region + account_id: .__AccountId + instance_type: .Properties.InstanceType + state: .Properties.State.Name + tags: .Properties.Tags + arn: .Properties.Arn + relations: + account: .__AccountId +``` + +## Complex Relationship Examples + +### ECS Cluster and Service Relationships + +Map ECS clusters and their services with relationships: + +```yaml showLineNumbers +resources: +# ECS Clusters +- kind: AWS::ECS::Cluster + selector: + query: 'true' + useGetResourceAPI: 'true' + port: + entity: + mappings: + - identifier: .Properties.ClusterArn + title: .Properties.ClusterName + blueprint: '"ecsCluster"' + properties: + kind: .__Kind + region: .__Region + account_id: .__AccountId + cluster_name: .Properties.ClusterName + status: .Properties.Status + running_tasks_count: .Properties.RunningTasksCount + pending_tasks_count: .Properties.PendingTasksCount + active_services_count: .Properties.ActiveServicesCount + capacity_providers: .Properties.CapacityProviders + tags: .Properties.Tags + arn: .Properties.ClusterArn + link: .Properties | select(.Arn != null) | "https://console.aws.amazon.com/go/view?arn=" + .Arn + relations: + account: .__AccountId + +# ECS Services +- kind: AWS::ECS::Service + selector: + query: 'true' + useGetResourceAPI: 'true' + port: + entity: + mappings: + - identifier: .Properties.ServiceArn + title: .Properties.ServiceName + blueprint: '"ecsService"' + properties: + kind: .__Kind + region: .__Region + account_id: .__AccountId + service_name: .Properties.ServiceName + cluster_arn: .Properties.ClusterArn + task_definition: .Properties.TaskDefinition + desired_count: .Properties.DesiredCount + running_count: .Properties.RunningCount + pending_count: .Properties.PendingCount + launch_type: .Properties.LaunchType + platform_version: .Properties.PlatformVersion + status: .Properties.Status + tags: .Properties.Tags + arn: .Properties.ServiceArn + link: .Properties | select(.Arn != null) | "https://console.aws.amazon.com/go/view?arn=" + .Arn + relations: + account: .__AccountId + cluster: .Properties.ClusterArn +``` + +## Performance Optimization Examples + +### Parallel Processing Configuration + +Configure the integration for optimal performance: + +```yaml showLineNumbers +# Performance configuration +performance: + parallel_processing: + enabled: true + max_concurrent_requests: 10 + max_concurrent_accounts: 5 + + caching: + enabled: true + cache_ttl: "1h" + cache_size: 1000 + + rate_limiting: + enabled: true + requests_per_second: 10 + burst_limit: 20 + +aws: + access_key_id: "YOUR_ACCESS_KEY" + secret_access_key: "YOUR_SECRET_KEY" + region: "us-east-1" + + # Enable performance optimizations + optimizations: + use_get_resource_api: true + parallel_discovery: true + smart_caching: true + +resources: + - kind: AWS::S3::Bucket + selector: + query: 'true' + useGetResourceAPI: 'true' + port: + entity: + mappings: + - identifier: .Identifier + title: .Identifier + blueprint: '"s3Bucket"' + properties: + kind: .__Kind + region: .Properties.RegionalDomainName | capture(".*\\.(?[^\\.]+)\\.amazonaws\\.com") | .region + account_id: .__AccountId + tags: .Properties.Tags + arn: .Properties.Arn + relations: + account: .__AccountId +``` + +## Error Handling Examples + +### Robust Error Handling + +Configure comprehensive error handling: + +```yaml showLineNumbers +# Error handling configuration +error_handling: + retry_policy: + max_retries: 3 + retry_delay: "5s" + exponential_backoff: true + + error_notification: + enabled: true + webhook_url: "https://your-webhook-url.com/errors" + email_notifications: ["admin@yourcompany.com"] + + fallback_behavior: + skip_failed_resources: true + continue_on_error: true + log_errors: true + +aws: + access_key_id: "YOUR_ACCESS_KEY" + secret_access_key: "YOUR_SECRET_KEY" + region: "us-east-1" + +resources: + - kind: AWS::S3::Bucket + selector: + query: 'true' + useGetResourceAPI: 'true' + port: + entity: + mappings: + - identifier: .Identifier + title: .Identifier + blueprint: '"s3Bucket"' + properties: + kind: .__Kind + region: .Properties.RegionalDomainName | capture(".*\\.(?[^\\.]+)\\.amazonaws\\.com") | .region + account_id: .__AccountId + tags: .Properties.Tags + arn: .Properties.Arn + # Add error handling for missing properties + creation_date: .Properties.CreationDate // "unknown" + versioning: .Properties.Versioning.Status // "unknown" + relations: + account: .__AccountId +``` + +## Custom Blueprint Examples + +### Custom Resource Blueprints + +Create custom blueprints for specific use cases: + +```yaml showLineNumbers +resources: +# Custom Application Blueprint +- kind: AWS::ECS::Service + selector: + query: 'true' + useGetResourceAPI: 'true' + port: + entity: + mappings: + - identifier: .Properties.ServiceArn + title: .Properties.ServiceName + blueprint: '"application"' + properties: + name: .Properties.ServiceName + type: '"microservice"' + environment: .Properties.Tags.Environment // "unknown" + team: .Properties.Tags.Team // "unknown" + cost_center: .Properties.Tags.CostCenter // "unknown" + status: .Properties.Status + desired_count: .Properties.DesiredCount + running_count: .Properties.RunningCount + cluster: .Properties.ClusterArn + task_definition: .Properties.TaskDefinition + launch_type: .Properties.LaunchType + tags: .Properties.Tags + arn: .Properties.ServiceArn + link: .Properties | select(.Arn != null) | "https://console.aws.amazon.com/go/view?arn=" + .Arn + relations: + account: .__AccountId + cluster: .Properties.ClusterArn + +# Custom Database Blueprint +- kind: AWS::RDS::DBInstance + selector: + query: 'true' + useGetResourceAPI: 'true' + port: + entity: + mappings: + - identifier: .Properties.DBInstanceIdentifier + title: .Properties.DBInstanceIdentifier + blueprint: '"database"' + properties: + name: .Properties.DBInstanceIdentifier + type: '"relational"' + engine: .Properties.Engine + version: .Properties.EngineVersion + environment: .Properties.TagList | select(.Key == "Environment") | .Value // "unknown" + team: .Properties.TagList | select(.Key == "Team") | .Value // "unknown" + cost_center: .Properties.TagList | select(.Key == "CostCenter") | .Value // "unknown" + status: .Properties.DBInstanceStatus + instance_class: .Properties.DBInstanceClass + allocated_storage: .Properties.AllocatedStorage + multi_az: .Properties.MultiAZ + backup_retention: .Properties.BackupRetentionPeriod + tags: .Properties.TagList + arn: .Properties.DBInstanceArn + link: .Properties | select(.DBInstanceArn != null) | "https://console.aws.amazon.com/go/view?arn=" + .DBInstanceArn + relations: + account: .__AccountId +``` + +## Testing and Validation + +### Configuration Validation + +Test your configuration before deployment: + +```bash showLineNumbers +# Validate configuration syntax +python -c "import yaml; yaml.safe_load(open('config.yaml'))" + +# Test resource discovery +python main.py --dry-run --config config.yaml + +# Validate mapping syntax +python main.py --validate-mappings --config config.yaml +``` + +### Performance Testing + +Test performance with different configurations: + +```bash showLineNumbers +# Test with small resource set +python main.py --config config-small.yaml --benchmark + +# Test with full resource set +python main.py --config config-full.yaml --benchmark + +# Compare performance +python benchmark.py --config1 config-small.yaml --config2 config-full.yaml +``` + +## Best Practices + +### 1. Resource Selection + +- Use specific resource kinds instead of broad queries +- Implement proper filtering to reduce API calls +- Use `useGetResourceAPI: 'true'` when available + +### 2. Performance Optimization + +- Enable parallel processing for large deployments +- Use caching for frequently accessed resources +- Implement rate limiting to respect AWS limits + +### 3. Error Handling + +- Implement comprehensive error handling +- Use fallback values for missing properties +- Set up monitoring and alerting + +### 4. Security + +- Use least privilege IAM policies +- Encrypt sensitive configuration data +- Implement proper access controls + +### 5. Maintenance + +- Regular configuration reviews +- Monitor performance metrics +- Update configurations as AWS services evolve diff --git a/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/installations/installation.md b/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/installations/installation.md new file mode 100644 index 0000000000..3147269919 --- /dev/null +++ b/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/installations/installation.md @@ -0,0 +1,301 @@ +--- +sidebar_position: 1 +--- + +import Tabs from "@theme/Tabs"; +import TabItem from "@theme/TabItem"; + +# Installation + +This guide will walk you through installing AWS Hosted by Port in your Port environment. + +## Prerequisites + +Before installing AWS Hosted by Port, ensure you have: + +1. **Port Ocean Account**: Access to Port's Ocean SaaS platform +2. **AWS Account(s)**: AWS account(s) with appropriate permissions +3. **AWS Organizations** (for multi-account): If using multiple accounts, set up AWS Organizations +4. **CloudFormation Access**: Ability to deploy CloudFormation stacks in your AWS accounts +5. **Beta Access**: Contact your Port representative to request access to this beta feature + +## Installation Process + +AWS Hosted by Port is available through **Port's Ocean SaaS platform** and requires you to create IAM roles in your AWS accounts to grant the integration access to read your resources. + +:::info How the Integration Works +AWS Hosted by Port runs on Port's infrastructure and connects to your AWS accounts using **OIDC (OpenID Connect)** authentication. This means: +- No need to share AWS access keys or secrets +- More secure than traditional access key authentication +- Uses IAM roles with temporary credentials +- Works with AWS Organizations for multi-account setups +- **Zero maintenance required** - Port handles all infrastructure management +- **Periodic synchronization** - Keeps your Port catalog up-to-date with your AWS resources +::: + +:::warning Beta Access Required +AWS Hosted by Port is currently in beta mode. Contact your Port representative to request access to this integration before proceeding with installation. +::: + +## Supported AWS Resources + +AWS Hosted by Port currently supports the following AWS resource types: + +- **S3 Buckets**: Complete bucket information including properties, tags, and metadata +- **ECS Clusters**: Cluster details, services, and task definitions +- **EC2 Instances**: Instance information, security groups, and networking details + +:::info More Resource Types Coming Soon +We're actively working on adding support for additional AWS resource types to provide comprehensive coverage of your AWS infrastructure. +::: + +## Installation Methods + + + + + +### Single Account Installation + +For a single AWS account, you'll deploy a CloudFormation stack that creates the necessary IAM roles. + +#### Step 1: Deploy CloudFormation Stack + +1. **Access the CloudFormation Template**: + - Navigate to the [single-account integration template](https://port-cloudformation-templates.s3.eu-west-1.amazonaws.com/stable/ocean/aws-v3/single-account-integration.yaml) + +2. **Deploy via AWS Console**: + - Go to AWS CloudFormation in your AWS Console + - Click **Create Stack** → **With new resources (standard)** + - Choose **Template is ready** → **Upload a template file** + - Upload the template or use the S3 URL directly + +3. **Configure Stack Parameters**: + - **Port Organisation ID**: Your Port organization ID (e.g., `org_1234567890`) + - **Integration Identifier**: A unique identifier for this integration (e.g., `aws-v3-prod`) + - **Custom Role Name**: Leave empty for auto-generated name, or specify a custom name + - **OIDC Provider URL**: Keep the default value (do not change) + - **OIDC JWT Subject**: Keep the default value (do not change) + - **Create OIDC Provider**: Set to `true` (unless you already have one) + +#### Step 2: Configure Integration in Port + +1. **Navigate to Port Ocean**: + - Go to your Port Ocean environment + - Navigate to **Integrations** + +2. **Add AWS Hosted by Port Integration**: + - Click **+ Add Integration** + - Select **AWS Hosted by Port** from the cloud providers section + - Enter your integration details: + - **Integration Identifier**: Must match what you used in CloudFormation + - **AWS Account ID**: Your AWS account ID + - **AWS Region**: Your primary AWS region + +3. **Verify Connection**: + - Port will automatically detect the IAM role created by CloudFormation + - The integration will start discovering your AWS resources + +:::tip Why Can't I Use an Existing Role? +AWS Hosted by Port requires specific OIDC trust relationships and permissions that are automatically configured by the CloudFormation template. Using an existing role would require manual configuration of these complex trust relationships, which is why we provide the CloudFormation template to ensure proper setup. +::: + + + + + +### Multi-Account Installation with AWS Organizations + +For multiple AWS accounts, you'll use AWS Organizations and deploy the integration across multiple accounts using CloudFormation StackSets. + +:::info Understanding AWS Organizations +- **Master Account**: The main account that manages your organization +- **Member Accounts**: Individual AWS accounts in your organization +- **Organizational Units (OUs)**: Logical groupings of accounts (like folders) +- **OU IDs**: Unique identifiers for organizational units (e.g., `ou-abcd-12345678`) +::: + +#### Step 1: Prepare Your Organization + +1. **Access Master Account**: + - Log into your AWS Organizations master account + - Navigate to **AWS Organizations** service + +2. **Identify Target OUs**: + - Go to **Organizational units** in the AWS Organizations console + - Note the OU IDs you want to include (e.g., `ou-abcd-12345678`) + - You can also target specific account IDs if needed + +:::caution Master Account Access Required +You must run the multi-account installation from your AWS Organizations **master account**. This is because only the master account can deploy StackSets across member accounts. +::: + +#### Step 2: Deploy Multi-Account CloudFormation Stack + +1. **Access the CloudFormation Template**: + - Navigate to the [multi-account integration template](https://port-cloudformation-templates.s3.eu-west-1.amazonaws.com/stable/ocean/aws-v3/multi-account-integration.yaml) + +2. **Deploy via AWS Console**: + - In your **master account**, go to AWS CloudFormation + - Click **Create Stack** → **With new resources (standard)** + - Choose **Template is ready** → **Upload a template file** + - Upload the template or use the S3 URL directly + +3. **Configure Stack Parameters**: + + **Scope of Rollout**: + - **Target OU IDs**: Comma-separated list of OU IDs (e.g., `ou-abcd-12345678,ou-efgh-87654321`) + - **Account Scope**: Choose from: + - `ALL`: All accounts in the specified OUs + - `INTERSECTION`: Only accounts that are in both the OUs and the specified account list + - `DIFFERENCE`: All accounts in OUs except those in the specified account list + - **Target Account IDs**: Comma-separated list of specific account IDs (e.g., `123456789012,098765432109`) + + **Port Identifiers**: + - **Port Organization ID**: Your Port organization ID (e.g., `org_1234567890`) + - **Integration Identifier**: A unique identifier for this integration (e.g., `aws-v3-multi`) + + **IAM Role Settings**: + - **Custom Role Name**: Leave empty for auto-generated name, or specify a custom name + + **OIDC Settings**: + - **OIDC Provider URL**: Keep the default value (do not change) + - **OIDC JWT Subject**: Keep the default value (do not change) + + **Advanced**: + - **StackSet Name**: Custom name for the StackSet (default: `Port-Integration-v3`) + - **Create OIDC Provider**: Set to `true` (unless you already have one) + +:::tip Account Filtering Examples +- **All accounts in OU**: Set Account Scope to `ALL`, leave Target Account IDs empty +- **Specific accounts only**: Set Account Scope to `INTERSECTION`, specify account IDs +- **All except specific accounts**: Set Account Scope to `DIFFERENCE`, specify account IDs to exclude +::: + +#### Step 3: Monitor Deployment + +1. **Check StackSet Status**: + - Go to **CloudFormation** → **StackSets** in your master account + - Monitor the deployment progress across all target accounts + - Ensure all stack instances show "CURRENT" status + +2. **Verify IAM Roles**: + - Check that the IAM roles were created in each target account + - Verify the roles have the correct trust relationships + +#### Step 4: Configure Integration in Port + +1. **Navigate to Port Ocean**: + - Go to your Port Ocean environment + - Navigate to **Integrations** + +2. **Add AWS Hosted by Port Integration**: + - Click **+ Add Integration** + - Select **AWS Hosted by Port** from the cloud providers section + - Enter your integration details: + - **Integration Identifier**: Must match what you used in CloudFormation + - **AWS Organization ID**: Your AWS Organizations ID + - **Target Accounts**: Specify which accounts to include + +3. **Verify Multi-Account Connection**: + - Port will automatically detect the IAM roles across all accounts + - The integration will start discovering resources from all configured accounts + + + + + +## Post-Installation Configuration + +### 1. Verify Installation + +After installation, verify that the integration is working: + +1. **Check Integration Status**: + - Go to **Settings** → **Integrations** + - Verify the AWS-v3 integration shows as "Active" + - Check for any error messages + +2. **Verify Data Flow**: + - Go to **Software Catalog** + - Look for entities created by the integration + - Verify that AWS resources are being imported correctly + +### 2. Configure Blueprints + +The integration creates default blueprints, but you may want to customize them: + +1. **Review Default Blueprints**: + - `awsAccount`: For AWS accounts + - `cloudResource`: For general AWS resources + +2. **Customize Blueprints**: + - Add additional properties as needed + - Configure relations between resources + - Set up proper identifiers and titles + +### 3. Set Up Monitoring + +Configure monitoring for your integration: + +1. **Enable Logging**: + - Set up log aggregation + - Configure log levels + - Set up alerts for errors + +2. **Monitor Performance**: + - Track API call rates + - Monitor resource discovery performance + - Set up dashboards for key metrics + +## Troubleshooting + +### Common Installation Issues + +#### 1. Authentication Errors + +**Problem**: AWS authentication failures + +**Solution**: +- Verify AWS credentials are correct +- Check IAM permissions +- Ensure the AWS region is properly configured + +#### 2. Port API Errors + +**Problem**: Cannot connect to Port API + +**Solution**: +- Verify Port credentials +- Check network connectivity +- Ensure the Port base URL is correct + +#### 3. Resource Discovery Issues + +**Problem**: Resources not being discovered + +**Solution**: +- Check AWS permissions for resource listing +- Verify the resource kinds in your configuration +- Review selector queries + +### Getting Help + +If you encounter issues during installation: + +1. **Check Logs**: Review integration logs for error details +2. **Documentation**: Refer to the [AWS-v3 documentation](../aws-v3.md) +3. **Community**: Ask questions in the [Port Community Forum](https://github.com/port-labs/port/discussions) +4. **Support**: Contact Port support for enterprise customers + +## Next Steps + +After successful installation: + +1. **Configure Multiple Accounts**: Set up [multi-account support](./multi_account.md) +2. **Customize Mapping**: Learn about [advanced configuration](../aws-v3.md#advanced-configuration) +3. **Set Up Monitoring**: Configure [monitoring and alerting](../aws-v3.md#troubleshooting) +4. **Optimize Performance**: Review [performance tuning](../aws-v3.md#resource-discovery-optimization) diff --git a/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/installations/multi_account.md b/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/installations/multi_account.md new file mode 100644 index 0000000000..e556ea60e8 --- /dev/null +++ b/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/installations/multi_account.md @@ -0,0 +1,316 @@ +--- +sidebar_position: 2 +--- + +# Multi-Account Configuration + +This guide explains how to configure AWS Hosted by Port to work with multiple AWS accounts using AWS Organizations and CloudFormation StackSets. + +## Overview + +AWS Hosted by Port supports multiple AWS accounts through **AWS Organizations** using CloudFormation StackSets. This approach provides: + +- **Centralized Management**: Deploy the integration across multiple accounts from a single master account +- **OIDC Authentication**: Secure authentication using OpenID Connect without sharing credentials +- **Automated Deployment**: CloudFormation StackSets automatically deploy IAM roles to all target accounts +- **Account Filtering**: Flexible targeting of specific accounts or organizational units +- **Periodic Synchronization**: Regular updates across all accounts to keep your Port catalog current + +## Prerequisites + +Before setting up multi-account support: + +1. **AWS Organizations**: Set up AWS Organizations with a master account +2. **Master Account Access**: Administrative access to your AWS Organizations master account +3. **CloudFormation Permissions**: Ability to deploy CloudFormation StackSets +4. **Port Ocean Account**: Access to Port's Ocean SaaS platform + +## Understanding AWS Organizations + +Before proceeding, it's important to understand key AWS Organizations concepts: + +### Key Terms + +- **Master Account**: The main account that manages your organization (also called "management account") +- **Member Accounts**: Individual AWS accounts in your organization +- **Organizational Units (OUs)**: Logical groupings of accounts (like folders in a file system) +- **OU IDs**: Unique identifiers for organizational units (format: `ou-abcd-12345678`) + +### Finding Your OU IDs + +1. **Access AWS Organizations**: + - Log into your AWS Organizations master account + - Navigate to **AWS Organizations** service + +2. **Locate OU IDs**: + - Go to **Organizational units** in the left sidebar + - Click on any organizational unit + - The OU ID is displayed in the details (e.g., `ou-abcd-12345678`) + +:::info Why OU IDs Matter +OU IDs are used to target specific groups of accounts for deployment. You can deploy the integration to all accounts in an OU, or use account filtering to be more selective. +::: + +## Multi-Account Installation Process + +The AWS-v3 integration uses CloudFormation StackSets to deploy IAM roles across multiple accounts. Here's how it works: + +### Step 1: Deploy Multi-Account CloudFormation Stack + +1. **Access the CloudFormation Template**: + - Navigate to the [multi-account integration template](https://port-cloudformation-templates.s3.eu-west-1.amazonaws.com/stable/ocean/aws-v3/multi-account-integration.yaml) + +2. **Deploy via AWS Console**: + - In your **master account**, go to AWS CloudFormation + - Click **Create Stack** → **With new resources (standard)** + - Choose **Template is ready** → **Upload a template file** + - Upload the template or use the S3 URL directly + +3. **Configure Stack Parameters**: + + **Scope of Rollout**: + - **Target OU IDs**: Comma-separated list of OU IDs (e.g., `ou-abcd-12345678,ou-efgh-87654321`) + - **Account Scope**: Choose from: + - `ALL`: All accounts in the specified OUs + - `INTERSECTION`: Only accounts that are in both the OUs and the specified account list + - `DIFFERENCE`: All accounts in OUs except those in the specified account list + - **Target Account IDs**: Comma-separated list of specific account IDs (e.g., `123456789012,098765432109`) + + **Port Identifiers**: + - **Port Organization ID**: Your Port organization ID (e.g., `org_1234567890`) + - **Integration Identifier**: A unique identifier for this integration (e.g., `aws-v3-multi`) + + **IAM Role Settings**: + - **Custom Role Name**: Leave empty for auto-generated name, or specify a custom name + + **OIDC Settings**: + - **OIDC Provider URL**: Keep the default value (do not change) + - **OIDC JWT Subject**: Keep the default value (do not change) + + **Advanced**: + - **StackSet Name**: Custom name for the StackSet (default: `Port-Integration-v3`) + - **Create OIDC Provider**: Set to `true` (unless you already have one) + +### Step 2: Understanding Account Filtering + +The CloudFormation template provides flexible account targeting: + +#### Account Scope Options + +- **ALL**: Deploy to all accounts in the specified OUs + - Example: Deploy to all accounts in `ou-prod-12345678` + - Leave "Target Account IDs" empty + +- **INTERSECTION**: Deploy only to accounts that are in both the OUs AND the account list + - Example: Deploy only to accounts `123456789012` and `234567890123` if they're in `ou-prod-12345678` + - Specify both OU IDs and Target Account IDs + +- **DIFFERENCE**: Deploy to all accounts in OUs EXCEPT those in the account list + - Example: Deploy to all accounts in `ou-prod-12345678` except `345678901234` + - Specify OU IDs and accounts to exclude + +#### Examples + +**Deploy to all production accounts**: +- Target OU IDs: `ou-prod-12345678` +- Account Scope: `ALL` +- Target Account IDs: (leave empty) + +**Deploy to specific accounts only**: +- Target OU IDs: `ou-prod-12345678,ou-staging-87654321` +- Account Scope: `INTERSECTION` +- Target Account IDs: `123456789012,234567890123` + +**Deploy to all accounts except test accounts**: +- Target OU IDs: `ou-prod-12345678` +- Account Scope: `DIFFERENCE` +- Target Account IDs: `345678901234,456789012345` + +### Step 3: Monitor Deployment + +1. **Check StackSet Status**: + - Go to **CloudFormation** → **StackSets** in your master account + - Monitor the deployment progress across all target accounts + - Ensure all stack instances show "CURRENT" status + +2. **Verify IAM Roles**: + - Check that the IAM roles were created in each target account + - Verify the roles have the correct trust relationships + +### Step 4: Configure Integration in Port + +1. **Navigate to Port Ocean**: + - Go to your Port Ocean environment + - Navigate to **Integrations** + +2. **Add AWS Hosted by Port Integration**: + - Click **+ Add Integration** + - Select **AWS Hosted by Port** from the cloud providers section + - Enter your integration details: + - **Integration Identifier**: Must match what you used in CloudFormation + - **AWS Organization ID**: Your AWS Organizations ID + - **Target Accounts**: Specify which accounts to include + +3. **Verify Multi-Account Connection**: + - Port will automatically detect the IAM roles across all accounts + - The integration will start discovering resources from all configured accounts + +## Common Configuration Issues + +### Issue 1: "Client did not know what is OU" + +**Problem**: Users are unfamiliar with AWS Organizations terminology. + +**Solution**: +- Explain that OUs are like folders that group AWS accounts +- Show them how to find OU IDs in the AWS Organizations console +- Provide examples of common OU structures (Production, Development, Staging) + +### Issue 2: "Client didn't know he needs to go to the master account" + +**Problem**: Users try to deploy from member accounts instead of the master account. + +**Solution**: +- Clearly explain that multi-account deployment must be done from the master account +- Provide instructions on how to identify the master account +- Explain why this is necessary (only master accounts can deploy StackSets) + +### Issue 3: "Client didn't understand how the installation works" + +**Problem**: Users don't understand the OIDC-based authentication model. + +**Solution**: +- Explain that the integration runs on Port's infrastructure +- Clarify that no AWS credentials are shared +- Describe how OIDC provides secure, temporary access + +### Issue 4: "Client didn't understand why he can't use an existing role" + +**Problem**: Users want to reuse existing IAM roles. + +**Solution**: +- Explain that the integration requires specific OIDC trust relationships +- Describe how the CloudFormation template configures these automatically +- Mention that manual configuration would be complex and error-prone + +### Issue 5: "Client didn't understand the filter accounts is used by account id and separated by ," + +**Problem**: Users don't understand the account filtering syntax. + +**Solution**: +- Provide clear examples of comma-separated account IDs +- Show different filtering scenarios (ALL, INTERSECTION, DIFFERENCE) +- Include visual examples with actual account IDs + +## Best Practices + +### 1. Security + +- **Least Privilege**: The CloudFormation template creates roles with read-only access +- **OIDC Authentication**: More secure than traditional access keys +- **Audit Logging**: Enable CloudTrail for all accounts +- **Regular Reviews**: Periodically review IAM roles and permissions + +### 2. Organization Structure + +- **Logical Grouping**: Organize accounts into meaningful OUs +- **Naming Conventions**: Use consistent naming for OUs and accounts +- **Environment Separation**: Separate production, staging, and development accounts + +### 3. Deployment Strategy + +- **Staged Rollout**: Deploy to non-production accounts first +- **Testing**: Verify the integration works in one account before rolling out to all +- **Monitoring**: Monitor deployment status across all accounts + +### 4. Maintenance + +- **Regular Updates**: Keep the CloudFormation templates updated +- **Account Management**: Add new accounts to appropriate OUs +- **Cleanup**: Remove access for accounts that no longer need it + +## Troubleshooting + +### Common Issues + +#### 1. StackSet Deployment Failures + +**Problem**: StackSet deployment fails on some accounts + +**Solution**: +- Check CloudFormation events for specific error messages +- Verify that target accounts have the necessary permissions +- Ensure accounts are in the correct OUs + +#### 2. IAM Role Creation Issues + +**Problem**: IAM roles are not created in target accounts + +**Solution**: +- Verify StackSet deployment status +- Check IAM permissions in target accounts +- Ensure the integration identifier matches between CloudFormation and Port + +#### 3. Port Integration Connection Issues + +**Problem**: Port cannot connect to AWS accounts + +**Solution**: +- Verify IAM roles exist in target accounts +- Check OIDC provider configuration +- Ensure integration identifier matches + +### Debug Mode + +Enable debug mode for detailed logging: + +```yaml showLineNumbers +debug: true +log_level: "DEBUG" + +aws: + debug: true + log_requests: true + log_responses: true +``` + +This will provide detailed information about: +- Cross-account role assumptions +- Account discovery process +- Resource discovery per account +- API call details and responses + +## Migration Guide + +### From Single Account to Multi-Account + +1. **Backup Current Configuration**: Save your existing single-account configuration +2. **Set Up AWS Organizations**: Ensure your accounts are properly organized +3. **Deploy Multi-Account Stack**: Use the CloudFormation template to deploy across accounts +4. **Update Port Configuration**: Modify your Port integration to include multiple accounts +5. **Test and Validate**: Verify the integration works across all accounts +6. **Monitor Performance**: Ensure the integration performs well with multiple accounts + +### Configuration Migration + +```yaml showLineNumbers +# Before (Single Account) +integration: + identifier: "aws-v3-single" + account_id: "123456789012" + region: "us-east-1" + +# After (Multi-Account) +integration: + identifier: "aws-v3-multi" + organization_id: "o-1234567890" + target_accounts: ["123456789012", "234567890123", "345678901234"] + regions: ["us-east-1", "us-west-2"] +``` + +## Support and Resources + +- **AWS Organizations**: [AWS Organizations Documentation](https://docs.aws.amazon.com/organizations/) +- **CloudFormation StackSets**: [AWS CloudFormation StackSets Documentation](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/what-is-cfnstacksets.html) +- **Port Community**: [Port Community Forum](https://github.com/port-labs/port/discussions) +- **Issues**: [Report Issues](https://github.com/port-labs/ocean/issues) From 02cbbe93bbe56610c04db0efabe19c3f00fcd30c Mon Sep 17 00:00:00 2001 From: Shalev Avhar Date: Sun, 7 Sep 2025 09:51:58 +0300 Subject: [PATCH 02/16] refactor: Update AWS-v3 documentation to reflect integration name change - Changed references from "AWS-v3 integration" to "AWS Hosted by Port integration" throughout the documentation. - Updated example descriptions and installation instructions to align with the new naming convention. - Enhanced clarity in troubleshooting and configuration sections to improve user experience. --- .../cloud-providers/aws-v3/aws-v3.md | 10 +- .../aws-v3/examples/_category_.json | 2 +- .../aws-v3/installations/installation.md | 183 ++++++++++-------- 3 files changed, 110 insertions(+), 85 deletions(-) diff --git a/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/aws-v3.md b/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/aws-v3.md index 955f8f7165..891cc7a50e 100644 --- a/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/aws-v3.md +++ b/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/aws-v3.md @@ -214,7 +214,7 @@ resources: ### AWS SDK v3 Specific Features -The AWS-v3 integration leverages several AWS SDK v3 specific features: +The AWS Hosted by Port integration leverages several AWS SDK v3 specific features: - **Modular Architecture**: Only imports the specific AWS services you need, reducing bundle size - **Enhanced TypeScript Support**: Full TypeScript support with better type inference @@ -223,7 +223,7 @@ The AWS-v3 integration leverages several AWS SDK v3 specific features: ### Resource Discovery Optimization -The AWS-v3 integration includes several optimizations for resource discovery: +The AWS Hosted by Port integration includes several optimizations for resource discovery: - **Parallel Processing**: Processes multiple regions and services in parallel - **Smart Caching**: Implements intelligent caching to reduce API calls @@ -285,7 +285,7 @@ resources: If you encounter compatibility issues with AWS SDK v3: -1. Ensure you're using the latest version of the AWS-v3 integration +1. Ensure you're using the latest version of the AWS Hosted by Port integration 2. Check that your AWS credentials are properly configured 3. Verify that the required AWS services are available in your region @@ -322,7 +322,7 @@ This will provide detailed information about: ## Migration from AWS Integration -If you're migrating from the standard AWS integration to AWS-v3: +If you're migrating from the standard AWS integration to AWS Hosted by Port: 1. **Backup Configuration**: Save your current configuration 2. **Update Mapping**: Review and update your mapping configuration if needed @@ -343,4 +343,4 @@ The main differences in configuration: - **Documentation**: [AWS SDK v3 Documentation](https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/) - **Community**: [Port Community Forum](https://github.com/port-labs/port/discussions) - **Issues**: [Report Issues](https://github.com/port-labs/ocean/issues) -- **Source Code**: [AWS-v3 Integration](https://github.com/port-labs/ocean/tree/main/integrations/aws-v3) +- **Source Code**: [AWS Hosted by Port Integration](https://github.com/port-labs/ocean/tree/main/integrations/aws-v3) diff --git a/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/examples/_category_.json b/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/examples/_category_.json index b3a6656f62..9b52ac17a9 100644 --- a/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/examples/_category_.json +++ b/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/examples/_category_.json @@ -3,6 +3,6 @@ "position": 4, "link": { "type": "generated-index", - "description": "Comprehensive examples for configuring the AWS-v3 integration with various AWS services, filtering options, and advanced use cases." + "description": "Comprehensive examples for configuring the AWS Hosted by Port integration with various AWS services, filtering options, and advanced use cases." } } diff --git a/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/installations/installation.md b/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/installations/installation.md index 3147269919..11b5f6f024 100644 --- a/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/installations/installation.md +++ b/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/installations/installation.md @@ -9,16 +9,6 @@ import TabItem from "@theme/TabItem"; This guide will walk you through installing AWS Hosted by Port in your Port environment. -## Prerequisites - -Before installing AWS Hosted by Port, ensure you have: - -1. **Port Ocean Account**: Access to Port's Ocean SaaS platform -2. **AWS Account(s)**: AWS account(s) with appropriate permissions -3. **AWS Organizations** (for multi-account): If using multiple accounts, set up AWS Organizations -4. **CloudFormation Access**: Ability to deploy CloudFormation stacks in your AWS accounts -5. **Beta Access**: Contact your Port representative to request access to this beta feature - ## Installation Process AWS Hosted by Port is available through **Port's Ocean SaaS platform** and requires you to create IAM roles in your AWS accounts to grant the integration access to read your resources. @@ -66,17 +56,27 @@ For a single AWS account, you'll deploy a CloudFormation stack that creates the 1. **Access the CloudFormation Template**: - Navigate to the [single-account integration template](https://port-cloudformation-templates.s3.eu-west-1.amazonaws.com/stable/ocean/aws-v3/single-account-integration.yaml) + - Download the template or copy the S3 URL for direct deployment 2. **Deploy via AWS Console**: - - Go to AWS CloudFormation in your AWS Console + - Go to [AWS CloudFormation](https://console.aws.amazon.com/cloudformation/) in your AWS Console - Click **Create Stack** → **With new resources (standard)** - Choose **Template is ready** → **Upload a template file** - - Upload the template or use the S3 URL directly + - Upload the downloaded template or paste the S3 URL directly 3. **Configure Stack Parameters**: + + **Required Parameters**: - **Port Organisation ID**: Your Port organization ID (e.g., `org_1234567890`) + - *Find this in Port → Settings → General* - **Integration Identifier**: A unique identifier for this integration (e.g., `aws-v3-prod`) + - *Use lowercase letters, numbers, and hyphens only* + + **Optional Parameters**: - **Custom Role Name**: Leave empty for auto-generated name, or specify a custom name + - *Default: `PortIntegrationRole-{IntegrationIdentifier}`* + + **Advanced Parameters** (keep defaults unless you have specific requirements): - **OIDC Provider URL**: Keep the default value (do not change) - **OIDC JWT Subject**: Keep the default value (do not change) - **Create OIDC Provider**: Set to `true` (unless you already have one) @@ -85,15 +85,18 @@ For a single AWS account, you'll deploy a CloudFormation stack that creates the 1. **Navigate to Port Ocean**: - Go to your Port Ocean environment - - Navigate to **Integrations** + - Navigate to **Settings** → **Integrations** 2. **Add AWS Hosted by Port Integration**: - Click **+ Add Integration** - Select **AWS Hosted by Port** from the cloud providers section - Enter your integration details: - **Integration Identifier**: Must match what you used in CloudFormation - - **AWS Account ID**: Your AWS account ID + - *Example: `aws-v3-production`* + - **AWS Account ID**: Your AWS account ID (12-digit number) + - *Find this in AWS Console → Account menu* - **AWS Region**: Your primary AWS region + - *Example: `us-east-1`, `us-west-2`, `eu-west-1`* 3. **Verify Connection**: - Port will automatically detect the IAM role created by CloudFormation @@ -112,23 +115,49 @@ AWS Hosted by Port requires specific OIDC trust relationships and permissions th For multiple AWS accounts, you'll use AWS Organizations and deploy the integration across multiple accounts using CloudFormation StackSets. :::info Understanding AWS Organizations -- **Master Account**: The main account that manages your organization +- **Master Account**: The main account that manages your organization (also called "management account") - **Member Accounts**: Individual AWS accounts in your organization -- **Organizational Units (OUs)**: Logical groupings of accounts (like folders) -- **OU IDs**: Unique identifiers for organizational units (e.g., `ou-abcd-12345678`) +- **Organizational Units (OUs)**: Logical groupings of accounts (like folders in a file system) +- **OU IDs**: Unique identifiers for organizational units (format: `ou-abcd-12345678`) + +**Example Organization Structure**: +``` +Master Account (123456789012) +├── Production OU (ou-prod-12345678) +│ ├── Account: prod-app (234567890123) +│ └── Account: prod-db (345678901234) +├── Staging OU (ou-staging-87654321) +│ └── Account: staging (456789012345) +└── Development OU (ou-dev-11223344) + └── Account: dev (567890123456) +``` ::: #### Step 1: Prepare Your Organization 1. **Access Master Account**: - Log into your AWS Organizations master account - - Navigate to **AWS Organizations** service + - Navigate to [AWS Organizations](https://console.aws.amazon.com/organizations/) service -2. **Identify Target OUs**: - - Go to **Organizational units** in the AWS Organizations console - - Note the OU IDs you want to include (e.g., `ou-abcd-12345678`) +2. **Find Your OU IDs**: + - Go to **Organizational units** in the left sidebar + - Click on each organizational unit you want to target + - Copy the OU ID from the details page (format: `ou-abcd-12345678`) - You can also target specific account IDs if needed +:::tip Finding OU IDs +1. Go to AWS Organizations → Organizational units +2. Click on the OU name (e.g., "Production") +3. Copy the OU ID from the details (e.g., `ou-prod-12345678`) +4. Repeat for each OU you want to include + +**Common OU Naming Patterns**: +- `ou-prod-12345678` (Production) +- `ou-staging-87654321` (Staging) +- `ou-dev-11223344` (Development) +- `ou-shared-55667788` (Shared Services) +::: + :::caution Master Account Access Required You must run the multi-account installation from your AWS Organizations **master account**. This is because only the master account can deploy StackSets across member accounts. ::: @@ -147,32 +176,54 @@ You must run the multi-account installation from your AWS Organizations **master 3. **Configure Stack Parameters**: **Scope of Rollout**: - - **Target OU IDs**: Comma-separated list of OU IDs (e.g., `ou-abcd-12345678,ou-efgh-87654321`) + - **Target OU IDs**: Comma-separated list of OU IDs + - *Example: `ou-prod-12345678,ou-staging-87654321`* - **Account Scope**: Choose from: - `ALL`: All accounts in the specified OUs - `INTERSECTION`: Only accounts that are in both the OUs and the specified account list - `DIFFERENCE`: All accounts in OUs except those in the specified account list - - **Target Account IDs**: Comma-separated list of specific account IDs (e.g., `123456789012,098765432109`) + - **Target Account IDs**: Comma-separated list of specific account IDs + - *Example: `123456789012,098765432109`* **Port Identifiers**: - - **Port Organization ID**: Your Port organization ID (e.g., `org_1234567890`) - - **Integration Identifier**: A unique identifier for this integration (e.g., `aws-v3-multi`) + - **Port Organization ID**: Your Port organization ID + - *Example: `org_abc123def456`* + - **Integration Identifier**: A unique identifier for this integration + - *Example: `aws-v3-multi-account`* **IAM Role Settings**: - **Custom Role Name**: Leave empty for auto-generated name, or specify a custom name + - *Default: `PortIntegrationRole-{IntegrationIdentifier}`* - **OIDC Settings**: + **OIDC Settings** (keep defaults): - **OIDC Provider URL**: Keep the default value (do not change) - **OIDC JWT Subject**: Keep the default value (do not change) **Advanced**: - - **StackSet Name**: Custom name for the StackSet (default: `Port-Integration-v3`) + - **StackSet Name**: Custom name for the StackSet + - *Default: `Port-Integration-v3`* - **Create OIDC Provider**: Set to `true` (unless you already have one) :::tip Account Filtering Examples -- **All accounts in OU**: Set Account Scope to `ALL`, leave Target Account IDs empty -- **Specific accounts only**: Set Account Scope to `INTERSECTION`, specify account IDs -- **All except specific accounts**: Set Account Scope to `DIFFERENCE`, specify account IDs to exclude + +**Scenario 1: Deploy to all production accounts** +- Target OU IDs: `ou-prod-12345678` +- Account Scope: `ALL` +- Target Account IDs: (leave empty) +- *Result: All accounts in the Production OU* + +**Scenario 2: Deploy to specific accounts only** +- Target OU IDs: `ou-prod-12345678,ou-staging-87654321` +- Account Scope: `INTERSECTION` +- Target Account IDs: `123456789012,234567890123` +- *Result: Only these 2 accounts if they're in the specified OUs* + +**Scenario 3: Deploy to all accounts except test accounts** +- Target OU IDs: `ou-prod-12345678` +- Account Scope: `DIFFERENCE` +- Target Account IDs: `345678901234,456789012345` +- *Result: All accounts in Production OU except the 2 test accounts* + ::: #### Step 3: Monitor Deployment @@ -208,15 +259,13 @@ You must run the multi-account installation from your AWS Organizations **master -## Post-Installation Configuration - -### 1. Verify Installation +## Verify Installation After installation, verify that the integration is working: 1. **Check Integration Status**: - Go to **Settings** → **Integrations** - - Verify the AWS-v3 integration shows as "Active" + - Verify the AWS Hosted by Port integration shows as "Active" - Check for any error messages 2. **Verify Data Flow**: @@ -224,70 +273,45 @@ After installation, verify that the integration is working: - Look for entities created by the integration - Verify that AWS resources are being imported correctly -### 2. Configure Blueprints - -The integration creates default blueprints, but you may want to customize them: - -1. **Review Default Blueprints**: - - `awsAccount`: For AWS accounts - - `cloudResource`: For general AWS resources - -2. **Customize Blueprints**: - - Add additional properties as needed - - Configure relations between resources - - Set up proper identifiers and titles - -### 3. Set Up Monitoring - -Configure monitoring for your integration: - -1. **Enable Logging**: - - Set up log aggregation - - Configure log levels - - Set up alerts for errors - -2. **Monitor Performance**: - - Track API call rates - - Monitor resource discovery performance - - Set up dashboards for key metrics ## Troubleshooting ### Common Installation Issues -#### 1. Authentication Errors +#### CloudFormation Stack Creation Failures -**Problem**: AWS authentication failures +**Error**: `Stack creation failed: CREATE_FAILED` -**Solution**: -- Verify AWS credentials are correct -- Check IAM permissions -- Ensure the AWS region is properly configured +**Solutions**: +- **Invalid Port Organization ID**: Verify the format is `org_` followed by alphanumeric characters +- **Duplicate Integration Identifier**: Use a unique identifier that hasn't been used before +- **Insufficient IAM Permissions**: Ensure your AWS user has CloudFormation and IAM permissions +- **OIDC Provider Already Exists**: Set "Create OIDC Provider" to `false` if you already have one -#### 2. Port API Errors +#### StackSet Deployment Failures (Multi-Account) -**Problem**: Cannot connect to Port API +**Error**: `StackSet deployment failed on account X` -**Solution**: -- Verify Port credentials -- Check network connectivity -- Ensure the Port base URL is correct +**Solutions**: +- **Target Account Not in OU**: Verify the account is actually in the specified organizational unit +- **Insufficient Permissions**: Ensure the master account has StackSets permissions +- **Account Suspended**: Check if the target account is suspended or has billing issues -#### 3. Resource Discovery Issues +#### Port Integration Connection Issues -**Problem**: Resources not being discovered +**Error**: `Integration shows "Failed" status in Port` -**Solution**: -- Check AWS permissions for resource listing -- Verify the resource kinds in your configuration -- Review selector queries +**Solutions**: +- **Integration Identifier Mismatch**: Ensure the identifier in Port matches CloudFormation exactly +- **IAM Role Not Found**: Verify the CloudFormation stack completed successfully +- **OIDC Trust Relationship Issues**: Check that the OIDC provider was created correctly ### Getting Help If you encounter issues during installation: 1. **Check Logs**: Review integration logs for error details -2. **Documentation**: Refer to the [AWS-v3 documentation](../aws-v3.md) +2. **Documentation**: Refer to the [AWS Hosted by Port documentation](../aws-v3.md) 3. **Community**: Ask questions in the [Port Community Forum](https://github.com/port-labs/port/discussions) 4. **Support**: Contact Port support for enterprise customers @@ -299,3 +323,4 @@ After successful installation: 2. **Customize Mapping**: Learn about [advanced configuration](../aws-v3.md#advanced-configuration) 3. **Set Up Monitoring**: Configure [monitoring and alerting](../aws-v3.md#troubleshooting) 4. **Optimize Performance**: Review [performance tuning](../aws-v3.md#resource-discovery-optimization) + From f1eacd007b294fd867f661e1107f6e47642504ae Mon Sep 17 00:00:00 2001 From: Shalev Avhar Date: Sun, 7 Sep 2025 13:42:33 +0300 Subject: [PATCH 03/16] docs: Enhance AWS Hosted by Port installation guide - Clarified the installation process by detailing the steps for creating IAM roles and accessing the AWS Console. - Updated the integration configuration steps to include obtaining the Role ARN and completing the setup in Port. - Revised terminology from "Master Account" to "Management Account" for accuracy in AWS Organizations context. - Improved the structure and clarity of the multi-account installation instructions. --- .../aws-v3/installations/installation.md | 83 +++++++++++-------- 1 file changed, 49 insertions(+), 34 deletions(-) diff --git a/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/installations/installation.md b/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/installations/installation.md index 11b5f6f024..83d0376903 100644 --- a/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/installations/installation.md +++ b/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/installations/installation.md @@ -11,16 +11,16 @@ This guide will walk you through installing AWS Hosted by Port in your Port envi ## Installation Process -AWS Hosted by Port is available through **Port's Ocean SaaS platform** and requires you to create IAM roles in your AWS accounts to grant the integration access to read your resources. +AWS Hosted by Port is available through **Port's Ocean SaaS platform**. The installation process is simple - you only need to create IAM roles in your AWS accounts to grant the integration access to read your resources. The integration handles everything else automatically. :::info How the Integration Works -AWS Hosted by Port runs on Port's infrastructure and connects to your AWS accounts using **OIDC (OpenID Connect)** authentication. This means: -- No need to share AWS access keys or secrets -- More secure than traditional access key authentication -- Uses IAM roles with temporary credentials -- Works with AWS Organizations for multi-account setups -- **Zero maintenance required** - Port handles all infrastructure management -- **Periodic synchronization** - Keeps your Port catalog up-to-date with your AWS resources +AWS Hosted by Port runs on **Port's servers** and connects to your AWS accounts using **OIDC (OpenID Connect)** authentication. Here's how it works: + +1. **You create IAM roles** in your AWS accounts using our CloudFormation templates +2. **Port's servers assume these roles** using OIDC to get temporary AWS credentials +3. **Port discovers your AWS resources** by calling AWS APIs with the assumed roles +4. **Port exports the resources** to your Port account in the software catalog +5. **Port periodically syncs** to keep your catalog up-to-date with your AWS infrastructure ::: :::warning Beta Access Required @@ -52,7 +52,13 @@ We're actively working on adding support for additional AWS resource types to pr For a single AWS account, you'll deploy a CloudFormation stack that creates the necessary IAM roles. -#### Step 1: Deploy CloudFormation Stack +#### Step 1: Access AWS Console + +1. **Log into your AWS account**: + - Go to [AWS Console](https://console.aws.amazon.com/) + - Sign in with your AWS account credentials + +#### Step 2: Deploy CloudFormation Stack 1. **Access the CloudFormation Template**: - Navigate to the [single-account integration template](https://port-cloudformation-templates.s3.eu-west-1.amazonaws.com/stable/ocean/aws-v3/single-account-integration.yaml) @@ -81,24 +87,26 @@ For a single AWS account, you'll deploy a CloudFormation stack that creates the - **OIDC JWT Subject**: Keep the default value (do not change) - **Create OIDC Provider**: Set to `true` (unless you already have one) -#### Step 2: Configure Integration in Port +#### Step 3: Configure Integration in Port 1. **Navigate to Port Ocean**: - Go to your Port Ocean environment - - Navigate to **Settings** → **Integrations** + - Navigate to **Integrations** 2. **Add AWS Hosted by Port Integration**: - Click **+ Add Integration** - Select **AWS Hosted by Port** from the cloud providers section - - Enter your integration details: - - **Integration Identifier**: Must match what you used in CloudFormation - - *Example: `aws-v3-production`* - - **AWS Account ID**: Your AWS account ID (12-digit number) - - *Find this in AWS Console → Account menu* - - **AWS Region**: Your primary AWS region - - *Example: `us-east-1`, `us-west-2`, `eu-west-1`* - -3. **Verify Connection**: + +3. **Get the Role ARN**: + - After CloudFormation deployment completes, go to the **Outputs** tab + - Copy the **Role ARN** value + +4. **Complete Integration Setup**: + - Return to the Port integration form + - Paste the **Role ARN** into the **Account Role Arn** field + - Click **Done** + +5. **Verify Connection**: - Port will automatically detect the IAM role created by CloudFormation - The integration will start discovering your AWS resources @@ -115,14 +123,16 @@ AWS Hosted by Port requires specific OIDC trust relationships and permissions th For multiple AWS accounts, you'll use AWS Organizations and deploy the integration across multiple accounts using CloudFormation StackSets. :::info Understanding AWS Organizations -- **Master Account**: The main account that manages your organization (also called "management account") +- **Management Account**: The main account that manages your organization (also called "master account") - **Member Accounts**: Individual AWS accounts in your organization - **Organizational Units (OUs)**: Logical groupings of accounts (like folders in a file system) - **OU IDs**: Unique identifiers for organizational units (format: `ou-abcd-12345678`) +- **Root**: The top-level container for all accounts and OUs (format: `r-xxxxxxxxx`) **Example Organization Structure**: ``` -Master Account (123456789012) +Root (r-123456789) +├── Management Account (123456789012) ├── Production OU (ou-prod-12345678) │ ├── Account: prod-app (234567890123) │ └── Account: prod-db (345678901234) @@ -135,8 +145,8 @@ Master Account (123456789012) #### Step 1: Prepare Your Organization -1. **Access Master Account**: - - Log into your AWS Organizations master account +1. **Access Management Account**: + - Log into your AWS Organizations management account - Navigate to [AWS Organizations](https://console.aws.amazon.com/organizations/) service 2. **Find Your OU IDs**: @@ -158,8 +168,8 @@ Master Account (123456789012) - `ou-shared-55667788` (Shared Services) ::: -:::caution Master Account Access Required -You must run the multi-account installation from your AWS Organizations **master account**. This is because only the master account can deploy StackSets across member accounts. +:::caution Management Account Access Required +You must run the multi-account installation from your AWS Organizations **management account**. This is because only the management account can deploy StackSets across member accounts. ::: #### Step 2: Deploy Multi-Account CloudFormation Stack @@ -168,7 +178,7 @@ You must run the multi-account installation from your AWS Organizations **master - Navigate to the [multi-account integration template](https://port-cloudformation-templates.s3.eu-west-1.amazonaws.com/stable/ocean/aws-v3/multi-account-integration.yaml) 2. **Deploy via AWS Console**: - - In your **master account**, go to AWS CloudFormation + - In your **management account**, go to AWS CloudFormation - Click **Create Stack** → **With new resources (standard)** - Choose **Template is ready** → **Upload a template file** - Upload the template or use the S3 URL directly @@ -229,7 +239,7 @@ You must run the multi-account installation from your AWS Organizations **master #### Step 3: Monitor Deployment 1. **Check StackSet Status**: - - Go to **CloudFormation** → **StackSets** in your master account + - Go to **CloudFormation** → **StackSets** in your management account - Monitor the deployment progress across all target accounts - Ensure all stack instances show "CURRENT" status @@ -246,12 +256,17 @@ You must run the multi-account installation from your AWS Organizations **master 2. **Add AWS Hosted by Port Integration**: - Click **+ Add Integration** - Select **AWS Hosted by Port** from the cloud providers section - - Enter your integration details: - - **Integration Identifier**: Must match what you used in CloudFormation - - **AWS Organization ID**: Your AWS Organizations ID - - **Target Accounts**: Specify which accounts to include -3. **Verify Multi-Account Connection**: +3. **Get the Role ARN**: + - After CloudFormation deployment completes, go to the **Outputs** tab + - Copy the **Management Account Role ARN** value + +4. **Complete Integration Setup**: + - Return to the Port integration form + - Paste the **Management Account Role ARN** into the **Account Role Arn** field + - Click **Done** + +5. **Verify Multi-Account Connection**: - Port will automatically detect the IAM roles across all accounts - The integration will start discovering resources from all configured accounts @@ -294,7 +309,7 @@ After installation, verify that the integration is working: **Solutions**: - **Target Account Not in OU**: Verify the account is actually in the specified organizational unit -- **Insufficient Permissions**: Ensure the master account has StackSets permissions +- **Insufficient Permissions**: Ensure the management account has StackSets permissions - **Account Suspended**: Check if the target account is suspended or has billing issues #### Port Integration Connection Issues From d2470dd15bc3ea68ae804685f802fbeb4f883af7 Mon Sep 17 00:00:00 2001 From: Shalev Avhar Date: Mon, 8 Sep 2025 11:19:10 +0300 Subject: [PATCH 04/16] docs: Update AWS installation instructions for StackSet status - Changed the status verification step from "CURRENT" to "CREATE_COMPLETE" to accurately reflect the expected state of stack instances during the multi-account installation process. --- .../cloud-providers/aws-v3/installations/installation.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/installations/installation.md b/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/installations/installation.md index 83d0376903..680f61e6c2 100644 --- a/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/installations/installation.md +++ b/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/installations/installation.md @@ -241,7 +241,7 @@ You must run the multi-account installation from your AWS Organizations **manage 1. **Check StackSet Status**: - Go to **CloudFormation** → **StackSets** in your management account - Monitor the deployment progress across all target accounts - - Ensure all stack instances show "CURRENT" status + - Ensure all stack instances show "CREATE_COMPLETE" status 2. **Verify IAM Roles**: - Check that the IAM roles were created in each target account From c7b9b828ee02d50afdc07dc15d2d011885156bb3 Mon Sep 17 00:00:00 2001 From: Shalev Avhar Date: Mon, 8 Sep 2025 11:39:26 +0300 Subject: [PATCH 05/16] docs: Revise AWS installation instructions for single and multi-account setups - Updated the steps for deploying CloudFormation stacks to streamline the process for both single and multi-account integrations. - Clarified navigation to the Port Data Sources and integration setup in the AWS Console. - Enhanced the configuration steps by emphasizing the review of pre-configured parameters and acknowledging IAM resource creation. - Removed outdated instructions and improved overall clarity for users. --- .../aws-v3/installations/installation.md | 148 +++--------------- 1 file changed, 24 insertions(+), 124 deletions(-) diff --git a/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/installations/installation.md b/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/installations/installation.md index 680f61e6c2..1b5e1dad3b 100644 --- a/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/installations/installation.md +++ b/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/installations/installation.md @@ -61,37 +61,23 @@ For a single AWS account, you'll deploy a CloudFormation stack that creates the #### Step 2: Deploy CloudFormation Stack 1. **Access the CloudFormation Template**: - - Navigate to the [single-account integration template](https://port-cloudformation-templates.s3.eu-west-1.amazonaws.com/stable/ocean/aws-v3/single-account-integration.yaml) - - Download the template or copy the S3 URL for direct deployment + - Go to [Port Data Sources](https://app.getport.io/settings/data-sources) + - Click **+ Add Integration** → **AWS Hosted by Port** + - Select **Single Account** and click the **"Click here"** link in step 3 + - This will open CloudFormation with pre-configured parameters 2. **Deploy via AWS Console**: - - Go to [AWS CloudFormation](https://console.aws.amazon.com/cloudformation/) in your AWS Console - - Click **Create Stack** → **With new resources (standard)** - - Choose **Template is ready** → **Upload a template file** - - Upload the downloaded template or paste the S3 URL directly - -3. **Configure Stack Parameters**: - - **Required Parameters**: - - **Port Organisation ID**: Your Port organization ID (e.g., `org_1234567890`) - - *Find this in Port → Settings → General* - - **Integration Identifier**: A unique identifier for this integration (e.g., `aws-v3-prod`) - - *Use lowercase letters, numbers, and hyphens only* - - **Optional Parameters**: - - **Custom Role Name**: Leave empty for auto-generated name, or specify a custom name - - *Default: `PortIntegrationRole-{IntegrationIdentifier}`* - - **Advanced Parameters** (keep defaults unless you have specific requirements): - - **OIDC Provider URL**: Keep the default value (do not change) - - **OIDC JWT Subject**: Keep the default value (do not change) - - **Create OIDC Provider**: Set to `true` (unless you already have one) + - In the CloudFormation console, review the pre-configured parameters + - Scroll down to the bottom of the page + - Check the box **"I acknowledge that AWS CloudFormation might create IAM resources with custom names"** + - Click **Create Stack** + #### Step 3: Configure Integration in Port -1. **Navigate to Port Ocean**: - - Go to your Port Ocean environment - - Navigate to **Integrations** +1. **Navigate to Port**: + - Go to your Port environment + - Navigate to **[Port Data Sources](https://app.getport.io/settings/data-sources)** 2. **Add AWS Hosted by Port Integration**: - Click **+ Add Integration** @@ -175,66 +161,17 @@ You must run the multi-account installation from your AWS Organizations **manage #### Step 2: Deploy Multi-Account CloudFormation Stack 1. **Access the CloudFormation Template**: - - Navigate to the [multi-account integration template](https://port-cloudformation-templates.s3.eu-west-1.amazonaws.com/stable/ocean/aws-v3/multi-account-integration.yaml) + - Go to [Port Data Sources](https://app.getport.io/settings/data-sources) + - Click **+ Add Integration** → **AWS Hosted by Port** + - Select **Multiple Accounts** and click the **"Click here"** link in step 3 + - This will open CloudFormation with pre-configured parameters 2. **Deploy via AWS Console**: - - In your **management account**, go to AWS CloudFormation - - Click **Create Stack** → **With new resources (standard)** - - Choose **Template is ready** → **Upload a template file** - - Upload the template or use the S3 URL directly - -3. **Configure Stack Parameters**: - - **Scope of Rollout**: - - **Target OU IDs**: Comma-separated list of OU IDs - - *Example: `ou-prod-12345678,ou-staging-87654321`* - - **Account Scope**: Choose from: - - `ALL`: All accounts in the specified OUs - - `INTERSECTION`: Only accounts that are in both the OUs and the specified account list - - `DIFFERENCE`: All accounts in OUs except those in the specified account list - - **Target Account IDs**: Comma-separated list of specific account IDs - - *Example: `123456789012,098765432109`* - - **Port Identifiers**: - - **Port Organization ID**: Your Port organization ID - - *Example: `org_abc123def456`* - - **Integration Identifier**: A unique identifier for this integration - - *Example: `aws-v3-multi-account`* - - **IAM Role Settings**: - - **Custom Role Name**: Leave empty for auto-generated name, or specify a custom name - - *Default: `PortIntegrationRole-{IntegrationIdentifier}`* - - **OIDC Settings** (keep defaults): - - **OIDC Provider URL**: Keep the default value (do not change) - - **OIDC JWT Subject**: Keep the default value (do not change) - - **Advanced**: - - **StackSet Name**: Custom name for the StackSet - - *Default: `Port-Integration-v3`* - - **Create OIDC Provider**: Set to `true` (unless you already have one) - -:::tip Account Filtering Examples - -**Scenario 1: Deploy to all production accounts** -- Target OU IDs: `ou-prod-12345678` -- Account Scope: `ALL` -- Target Account IDs: (leave empty) -- *Result: All accounts in the Production OU* - -**Scenario 2: Deploy to specific accounts only** -- Target OU IDs: `ou-prod-12345678,ou-staging-87654321` -- Account Scope: `INTERSECTION` -- Target Account IDs: `123456789012,234567890123` -- *Result: Only these 2 accounts if they're in the specified OUs* - -**Scenario 3: Deploy to all accounts except test accounts** -- Target OU IDs: `ou-prod-12345678` -- Account Scope: `DIFFERENCE` -- Target Account IDs: `345678901234,456789012345` -- *Result: All accounts in Production OU except the 2 test accounts* + - In the CloudFormation console, review the pre-configured parameters + - Scroll down to the bottom of the page + - Check the box **"I acknowledge that AWS CloudFormation might create IAM resources with custom names"** + - Click **Create Stack** -::: #### Step 3: Monitor Deployment @@ -245,13 +182,12 @@ You must run the multi-account installation from your AWS Organizations **manage 2. **Verify IAM Roles**: - Check that the IAM roles were created in each target account - - Verify the roles have the correct trust relationships #### Step 4: Configure Integration in Port -1. **Navigate to Port Ocean**: - - Go to your Port Ocean environment - - Navigate to **Integrations** +1. **Navigate to Port**: + - Go to your Port environment + - Navigate to **[Port Data Sources](https://app.getport.io/settings/data-sources)** 2. **Add AWS Hosted by Port Integration**: - Click **+ Add Integration** @@ -259,7 +195,7 @@ You must run the multi-account installation from your AWS Organizations **manage 3. **Get the Role ARN**: - After CloudFormation deployment completes, go to the **Outputs** tab - - Copy the **Management Account Role ARN** value + - Copy the **PortintegrationRoleArn** value 4. **Complete Integration Setup**: - Return to the Port integration form @@ -303,39 +239,3 @@ After installation, verify that the integration is working: - **Insufficient IAM Permissions**: Ensure your AWS user has CloudFormation and IAM permissions - **OIDC Provider Already Exists**: Set "Create OIDC Provider" to `false` if you already have one -#### StackSet Deployment Failures (Multi-Account) - -**Error**: `StackSet deployment failed on account X` - -**Solutions**: -- **Target Account Not in OU**: Verify the account is actually in the specified organizational unit -- **Insufficient Permissions**: Ensure the management account has StackSets permissions -- **Account Suspended**: Check if the target account is suspended or has billing issues - -#### Port Integration Connection Issues - -**Error**: `Integration shows "Failed" status in Port` - -**Solutions**: -- **Integration Identifier Mismatch**: Ensure the identifier in Port matches CloudFormation exactly -- **IAM Role Not Found**: Verify the CloudFormation stack completed successfully -- **OIDC Trust Relationship Issues**: Check that the OIDC provider was created correctly - -### Getting Help - -If you encounter issues during installation: - -1. **Check Logs**: Review integration logs for error details -2. **Documentation**: Refer to the [AWS Hosted by Port documentation](../aws-v3.md) -3. **Community**: Ask questions in the [Port Community Forum](https://github.com/port-labs/port/discussions) -4. **Support**: Contact Port support for enterprise customers - -## Next Steps - -After successful installation: - -1. **Configure Multiple Accounts**: Set up [multi-account support](./multi_account.md) -2. **Customize Mapping**: Learn about [advanced configuration](../aws-v3.md#advanced-configuration) -3. **Set Up Monitoring**: Configure [monitoring and alerting](../aws-v3.md#troubleshooting) -4. **Optimize Performance**: Review [performance tuning](../aws-v3.md#resource-discovery-optimization) - From 53b56270e267c7ed2b2fbe2a4a428d8377cc4162 Mon Sep 17 00:00:00 2001 From: Shalev Avhar Date: Mon, 8 Sep 2025 11:48:05 +0300 Subject: [PATCH 06/16] docs: Update AWS integration category positions and add installation guide - Adjusted the position values for the AWS and AWS Hosted by Port categories to maintain proper ordering. - Introduced a new category for "Installations" under AWS Hosted by Port with a defined position. - Added a comprehensive installation guide for AWS Hosted by Port, detailing the installation process, supported resources, and configuration steps for both single and multi-account setups. - Removed outdated multi-account configuration documentation to streamline the user experience. --- .../cloud-providers/aws-v3/_category_.json | 6 +- .../aws-v3/installations/_category_.json | 4 + .../{installation.md => installations.md} | 0 .../aws-v3/installations/multi_account.md | 316 ------------------ .../cloud-providers/aws/_category_.json | 2 +- 5 files changed, 6 insertions(+), 322 deletions(-) create mode 100644 docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/installations/_category_.json rename docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/installations/{installation.md => installations.md} (100%) delete mode 100644 docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/installations/multi_account.md diff --git a/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/_category_.json b/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/_category_.json index 1011f113cd..f17ac698a6 100644 --- a/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/_category_.json +++ b/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/_category_.json @@ -1,8 +1,4 @@ { "label": "AWS Hosted by Port", - "position": 3, - "link": { - "type": "generated-index", - "description": "AWS Hosted by Port integration documentation. Learn how to integrate your AWS resources with zero maintenance required - fully hosted and managed by Port." - } + "position": 12 } diff --git a/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/installations/_category_.json b/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/installations/_category_.json new file mode 100644 index 0000000000..d5a722de8d --- /dev/null +++ b/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/installations/_category_.json @@ -0,0 +1,4 @@ +{ + "label": "Installations", + "position": 1 +} \ No newline at end of file diff --git a/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/installations/installation.md b/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/installations/installations.md similarity index 100% rename from docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/installations/installation.md rename to docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/installations/installations.md diff --git a/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/installations/multi_account.md b/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/installations/multi_account.md deleted file mode 100644 index e556ea60e8..0000000000 --- a/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/installations/multi_account.md +++ /dev/null @@ -1,316 +0,0 @@ ---- -sidebar_position: 2 ---- - -# Multi-Account Configuration - -This guide explains how to configure AWS Hosted by Port to work with multiple AWS accounts using AWS Organizations and CloudFormation StackSets. - -## Overview - -AWS Hosted by Port supports multiple AWS accounts through **AWS Organizations** using CloudFormation StackSets. This approach provides: - -- **Centralized Management**: Deploy the integration across multiple accounts from a single master account -- **OIDC Authentication**: Secure authentication using OpenID Connect without sharing credentials -- **Automated Deployment**: CloudFormation StackSets automatically deploy IAM roles to all target accounts -- **Account Filtering**: Flexible targeting of specific accounts or organizational units -- **Periodic Synchronization**: Regular updates across all accounts to keep your Port catalog current - -## Prerequisites - -Before setting up multi-account support: - -1. **AWS Organizations**: Set up AWS Organizations with a master account -2. **Master Account Access**: Administrative access to your AWS Organizations master account -3. **CloudFormation Permissions**: Ability to deploy CloudFormation StackSets -4. **Port Ocean Account**: Access to Port's Ocean SaaS platform - -## Understanding AWS Organizations - -Before proceeding, it's important to understand key AWS Organizations concepts: - -### Key Terms - -- **Master Account**: The main account that manages your organization (also called "management account") -- **Member Accounts**: Individual AWS accounts in your organization -- **Organizational Units (OUs)**: Logical groupings of accounts (like folders in a file system) -- **OU IDs**: Unique identifiers for organizational units (format: `ou-abcd-12345678`) - -### Finding Your OU IDs - -1. **Access AWS Organizations**: - - Log into your AWS Organizations master account - - Navigate to **AWS Organizations** service - -2. **Locate OU IDs**: - - Go to **Organizational units** in the left sidebar - - Click on any organizational unit - - The OU ID is displayed in the details (e.g., `ou-abcd-12345678`) - -:::info Why OU IDs Matter -OU IDs are used to target specific groups of accounts for deployment. You can deploy the integration to all accounts in an OU, or use account filtering to be more selective. -::: - -## Multi-Account Installation Process - -The AWS-v3 integration uses CloudFormation StackSets to deploy IAM roles across multiple accounts. Here's how it works: - -### Step 1: Deploy Multi-Account CloudFormation Stack - -1. **Access the CloudFormation Template**: - - Navigate to the [multi-account integration template](https://port-cloudformation-templates.s3.eu-west-1.amazonaws.com/stable/ocean/aws-v3/multi-account-integration.yaml) - -2. **Deploy via AWS Console**: - - In your **master account**, go to AWS CloudFormation - - Click **Create Stack** → **With new resources (standard)** - - Choose **Template is ready** → **Upload a template file** - - Upload the template or use the S3 URL directly - -3. **Configure Stack Parameters**: - - **Scope of Rollout**: - - **Target OU IDs**: Comma-separated list of OU IDs (e.g., `ou-abcd-12345678,ou-efgh-87654321`) - - **Account Scope**: Choose from: - - `ALL`: All accounts in the specified OUs - - `INTERSECTION`: Only accounts that are in both the OUs and the specified account list - - `DIFFERENCE`: All accounts in OUs except those in the specified account list - - **Target Account IDs**: Comma-separated list of specific account IDs (e.g., `123456789012,098765432109`) - - **Port Identifiers**: - - **Port Organization ID**: Your Port organization ID (e.g., `org_1234567890`) - - **Integration Identifier**: A unique identifier for this integration (e.g., `aws-v3-multi`) - - **IAM Role Settings**: - - **Custom Role Name**: Leave empty for auto-generated name, or specify a custom name - - **OIDC Settings**: - - **OIDC Provider URL**: Keep the default value (do not change) - - **OIDC JWT Subject**: Keep the default value (do not change) - - **Advanced**: - - **StackSet Name**: Custom name for the StackSet (default: `Port-Integration-v3`) - - **Create OIDC Provider**: Set to `true` (unless you already have one) - -### Step 2: Understanding Account Filtering - -The CloudFormation template provides flexible account targeting: - -#### Account Scope Options - -- **ALL**: Deploy to all accounts in the specified OUs - - Example: Deploy to all accounts in `ou-prod-12345678` - - Leave "Target Account IDs" empty - -- **INTERSECTION**: Deploy only to accounts that are in both the OUs AND the account list - - Example: Deploy only to accounts `123456789012` and `234567890123` if they're in `ou-prod-12345678` - - Specify both OU IDs and Target Account IDs - -- **DIFFERENCE**: Deploy to all accounts in OUs EXCEPT those in the account list - - Example: Deploy to all accounts in `ou-prod-12345678` except `345678901234` - - Specify OU IDs and accounts to exclude - -#### Examples - -**Deploy to all production accounts**: -- Target OU IDs: `ou-prod-12345678` -- Account Scope: `ALL` -- Target Account IDs: (leave empty) - -**Deploy to specific accounts only**: -- Target OU IDs: `ou-prod-12345678,ou-staging-87654321` -- Account Scope: `INTERSECTION` -- Target Account IDs: `123456789012,234567890123` - -**Deploy to all accounts except test accounts**: -- Target OU IDs: `ou-prod-12345678` -- Account Scope: `DIFFERENCE` -- Target Account IDs: `345678901234,456789012345` - -### Step 3: Monitor Deployment - -1. **Check StackSet Status**: - - Go to **CloudFormation** → **StackSets** in your master account - - Monitor the deployment progress across all target accounts - - Ensure all stack instances show "CURRENT" status - -2. **Verify IAM Roles**: - - Check that the IAM roles were created in each target account - - Verify the roles have the correct trust relationships - -### Step 4: Configure Integration in Port - -1. **Navigate to Port Ocean**: - - Go to your Port Ocean environment - - Navigate to **Integrations** - -2. **Add AWS Hosted by Port Integration**: - - Click **+ Add Integration** - - Select **AWS Hosted by Port** from the cloud providers section - - Enter your integration details: - - **Integration Identifier**: Must match what you used in CloudFormation - - **AWS Organization ID**: Your AWS Organizations ID - - **Target Accounts**: Specify which accounts to include - -3. **Verify Multi-Account Connection**: - - Port will automatically detect the IAM roles across all accounts - - The integration will start discovering resources from all configured accounts - -## Common Configuration Issues - -### Issue 1: "Client did not know what is OU" - -**Problem**: Users are unfamiliar with AWS Organizations terminology. - -**Solution**: -- Explain that OUs are like folders that group AWS accounts -- Show them how to find OU IDs in the AWS Organizations console -- Provide examples of common OU structures (Production, Development, Staging) - -### Issue 2: "Client didn't know he needs to go to the master account" - -**Problem**: Users try to deploy from member accounts instead of the master account. - -**Solution**: -- Clearly explain that multi-account deployment must be done from the master account -- Provide instructions on how to identify the master account -- Explain why this is necessary (only master accounts can deploy StackSets) - -### Issue 3: "Client didn't understand how the installation works" - -**Problem**: Users don't understand the OIDC-based authentication model. - -**Solution**: -- Explain that the integration runs on Port's infrastructure -- Clarify that no AWS credentials are shared -- Describe how OIDC provides secure, temporary access - -### Issue 4: "Client didn't understand why he can't use an existing role" - -**Problem**: Users want to reuse existing IAM roles. - -**Solution**: -- Explain that the integration requires specific OIDC trust relationships -- Describe how the CloudFormation template configures these automatically -- Mention that manual configuration would be complex and error-prone - -### Issue 5: "Client didn't understand the filter accounts is used by account id and separated by ," - -**Problem**: Users don't understand the account filtering syntax. - -**Solution**: -- Provide clear examples of comma-separated account IDs -- Show different filtering scenarios (ALL, INTERSECTION, DIFFERENCE) -- Include visual examples with actual account IDs - -## Best Practices - -### 1. Security - -- **Least Privilege**: The CloudFormation template creates roles with read-only access -- **OIDC Authentication**: More secure than traditional access keys -- **Audit Logging**: Enable CloudTrail for all accounts -- **Regular Reviews**: Periodically review IAM roles and permissions - -### 2. Organization Structure - -- **Logical Grouping**: Organize accounts into meaningful OUs -- **Naming Conventions**: Use consistent naming for OUs and accounts -- **Environment Separation**: Separate production, staging, and development accounts - -### 3. Deployment Strategy - -- **Staged Rollout**: Deploy to non-production accounts first -- **Testing**: Verify the integration works in one account before rolling out to all -- **Monitoring**: Monitor deployment status across all accounts - -### 4. Maintenance - -- **Regular Updates**: Keep the CloudFormation templates updated -- **Account Management**: Add new accounts to appropriate OUs -- **Cleanup**: Remove access for accounts that no longer need it - -## Troubleshooting - -### Common Issues - -#### 1. StackSet Deployment Failures - -**Problem**: StackSet deployment fails on some accounts - -**Solution**: -- Check CloudFormation events for specific error messages -- Verify that target accounts have the necessary permissions -- Ensure accounts are in the correct OUs - -#### 2. IAM Role Creation Issues - -**Problem**: IAM roles are not created in target accounts - -**Solution**: -- Verify StackSet deployment status -- Check IAM permissions in target accounts -- Ensure the integration identifier matches between CloudFormation and Port - -#### 3. Port Integration Connection Issues - -**Problem**: Port cannot connect to AWS accounts - -**Solution**: -- Verify IAM roles exist in target accounts -- Check OIDC provider configuration -- Ensure integration identifier matches - -### Debug Mode - -Enable debug mode for detailed logging: - -```yaml showLineNumbers -debug: true -log_level: "DEBUG" - -aws: - debug: true - log_requests: true - log_responses: true -``` - -This will provide detailed information about: -- Cross-account role assumptions -- Account discovery process -- Resource discovery per account -- API call details and responses - -## Migration Guide - -### From Single Account to Multi-Account - -1. **Backup Current Configuration**: Save your existing single-account configuration -2. **Set Up AWS Organizations**: Ensure your accounts are properly organized -3. **Deploy Multi-Account Stack**: Use the CloudFormation template to deploy across accounts -4. **Update Port Configuration**: Modify your Port integration to include multiple accounts -5. **Test and Validate**: Verify the integration works across all accounts -6. **Monitor Performance**: Ensure the integration performs well with multiple accounts - -### Configuration Migration - -```yaml showLineNumbers -# Before (Single Account) -integration: - identifier: "aws-v3-single" - account_id: "123456789012" - region: "us-east-1" - -# After (Multi-Account) -integration: - identifier: "aws-v3-multi" - organization_id: "o-1234567890" - target_accounts: ["123456789012", "234567890123", "345678901234"] - regions: ["us-east-1", "us-west-2"] -``` - -## Support and Resources - -- **AWS Organizations**: [AWS Organizations Documentation](https://docs.aws.amazon.com/organizations/) -- **CloudFormation StackSets**: [AWS CloudFormation StackSets Documentation](https://docs.aws.amazon.com/AWSCloudFormation/latest/UserGuide/what-is-cfnstacksets.html) -- **Port Community**: [Port Community Forum](https://github.com/port-labs/port/discussions) -- **Issues**: [Report Issues](https://github.com/port-labs/ocean/issues) diff --git a/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws/_category_.json b/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws/_category_.json index 799b42596e..7597159280 100644 --- a/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws/_category_.json +++ b/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws/_category_.json @@ -1,4 +1,4 @@ { "label": "AWS", - "position": 10 + "position": 11 } From 97faf6f9b0417090b2edbad4753927230109e2c0 Mon Sep 17 00:00:00 2001 From: Shalev Avhar Date: Mon, 8 Sep 2025 11:51:33 +0300 Subject: [PATCH 07/16] docs: Correct installation guide link and remove outdated multi-account support section - Updated the installation guide link for AWS Hosted by Port to the correct path. - Removed the outdated section on multiple accounts support to streamline the documentation and avoid confusion. --- .../sync-data-to-catalog/cloud-providers/aws-v3/aws-v3.md | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/aws-v3.md b/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/aws-v3.md index 891cc7a50e..0989697a38 100644 --- a/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/aws-v3.md +++ b/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/aws-v3.md @@ -67,11 +67,8 @@ AWS Hosted by Port provides several advantages over the standard AWS integration ## Getting started -Continue to the [installation](./installations/installation.md) guide to learn how to install AWS Hosted by Port. +Continue to the [installation](./installations/installations.md) guide to learn how to install AWS Hosted by Port. -## Multiple accounts support - -To properly configure permissions for production and to enable multiple accounts collection check out our [multiple accounts guide](./installations/multi_account.md) ## Configuration @@ -340,7 +337,5 @@ The main differences in configuration: ## Support and Resources -- **Documentation**: [AWS SDK v3 Documentation](https://docs.aws.amazon.com/sdk-for-javascript/v3/developer-guide/) - **Community**: [Port Community Forum](https://github.com/port-labs/port/discussions) - **Issues**: [Report Issues](https://github.com/port-labs/ocean/issues) -- **Source Code**: [AWS Hosted by Port Integration](https://github.com/port-labs/ocean/tree/main/integrations/aws-v3) From 5ccb46526510133d46a8f819c194750c5356a397 Mon Sep 17 00:00:00 2001 From: Shalev Avhar Date: Mon, 8 Sep 2025 13:38:03 +0300 Subject: [PATCH 08/16] docs: Remove AWS Hosted by Port examples and category JSON files - Deleted the examples Markdown file and the associated category JSON for AWS Hosted by Port integration to streamline documentation and remove outdated content. --- .../aws-v3/examples/_category_.json | 8 - .../aws-v3/examples/examples.md | 619 ------------------ 2 files changed, 627 deletions(-) delete mode 100644 docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/examples/_category_.json delete mode 100644 docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/examples/examples.md diff --git a/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/examples/_category_.json b/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/examples/_category_.json deleted file mode 100644 index 9b52ac17a9..0000000000 --- a/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/examples/_category_.json +++ /dev/null @@ -1,8 +0,0 @@ -{ - "label": "Examples", - "position": 4, - "link": { - "type": "generated-index", - "description": "Comprehensive examples for configuring the AWS Hosted by Port integration with various AWS services, filtering options, and advanced use cases." - } -} diff --git a/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/examples/examples.md b/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/examples/examples.md deleted file mode 100644 index b4723357e3..0000000000 --- a/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/examples/examples.md +++ /dev/null @@ -1,619 +0,0 @@ ---- -sidebar_position: 4 ---- - -import Tabs from "@theme/Tabs"; -import TabItem from "@theme/TabItem"; - -# AWS Hosted by Port Examples - -This page provides comprehensive examples for configuring AWS Hosted by Port with the currently supported AWS services and use cases. - -## Currently Supported AWS Resources - -AWS Hosted by Port currently supports the following AWS resource types: - -- **S3 Buckets**: Complete bucket information including properties, tags, and metadata -- **ECS Clusters**: Cluster details, services, and task definitions -- **EC2 Instances**: Instance information, security groups, and networking details - -:::info More Resource Types Coming Soon -We're actively working on adding support for additional AWS resource types to provide comprehensive coverage of your AWS infrastructure. -::: - -## Basic Examples - -### S3 Buckets - -Map S3 buckets with detailed properties: - -```yaml showLineNumbers -resources: -- kind: AWS::S3::Bucket - selector: - query: 'true' - useGetResourceAPI: 'true' - port: - entity: - mappings: - - identifier: .Identifier - title: .Identifier - blueprint: '"s3Bucket"' - properties: - kind: .__Kind - region: .Properties.RegionalDomainName | capture(".*\\.(?[^\\.]+)\\.amazonaws\\.com") | .region - account_id: .__AccountId - creation_date: .Properties.CreationDate - tags: .Properties.Tags - arn: .Properties.Arn - link: .Properties | select(.Arn != null) | "https://console.aws.amazon.com/go/view?arn=" + .Arn - relations: - account: .__AccountId -``` - -### EC2 Instances - -Map EC2 instances with comprehensive details: - -```yaml showLineNumbers -resources: -- kind: AWS::EC2::Instance - selector: - query: 'true' - port: - entity: - mappings: - - identifier: .Identifier - title: .Identifier - blueprint: '"ec2Instance"' - properties: - kind: .__Kind - region: .__Region - account_id: .__AccountId - instance_type: .Properties.InstanceType - state: .Properties.State.Name - launch_time: .Properties.LaunchTime - public_ip: .Properties.PublicIpAddress - private_ip: .Properties.PrivateIpAddress - vpc_id: .Properties.VpcId - subnet_id: .Properties.SubnetId - security_groups: .Properties.SecurityGroups - tags: .Properties.Tags - arn: .Properties.Arn - link: .Properties | select(.Arn != null) | "https://console.aws.amazon.com/go/view?arn=" + .Arn - relations: - account: .__AccountId - vpc: .Properties.VpcId -``` - - -## Advanced Examples - -### ECS Clusters and Services - -Map ECS clusters and their services with relationships: - -```yaml showLineNumbers -resources: -# ECS Clusters -- kind: AWS::ECS::Cluster - selector: - query: 'true' - useGetResourceAPI: 'true' - port: - entity: - mappings: - - identifier: .Properties.ClusterArn - title: .Properties.ClusterName - blueprint: '"ecsCluster"' - properties: - kind: .__Kind - region: .__Region - account_id: .__AccountId - cluster_name: .Properties.ClusterName - status: .Properties.Status - running_tasks_count: .Properties.RunningTasksCount - pending_tasks_count: .Properties.PendingTasksCount - active_services_count: .Properties.ActiveServicesCount - capacity_providers: .Properties.CapacityProviders - tags: .Properties.Tags - arn: .Properties.ClusterArn - link: .Properties | select(.Arn != null) | "https://console.aws.amazon.com/go/view?arn=" + .Arn - relations: - account: .__AccountId - -# ECS Services -- kind: AWS::ECS::Service - selector: - query: 'true' - useGetResourceAPI: 'true' - port: - entity: - mappings: - - identifier: .Properties.ServiceArn - title: .Properties.ServiceName - blueprint: '"ecsService"' - properties: - kind: .__Kind - region: .__Region - account_id: .__AccountId - service_name: .Properties.ServiceName - cluster_arn: .Properties.ClusterArn - task_definition: .Properties.TaskDefinition - desired_count: .Properties.DesiredCount - running_count: .Properties.RunningCount - pending_count: .Properties.PendingCount - launch_type: .Properties.LaunchType - platform_version: .Properties.PlatformVersion - status: .Properties.Status - tags: .Properties.Tags - arn: .Properties.ServiceArn - link: .Properties | select(.Arn != null) | "https://console.aws.amazon.com/go/view?arn=" + .Arn - relations: - account: .__AccountId - cluster: .Properties.ClusterArn -``` - - -## Multi-Account Examples - -### Organization-Wide Resource Mapping - -Map resources across multiple accounts in an organization: - -```yaml showLineNumbers -resources: -# Organization Account -- kind: AWS::Organizations::Account - selector: - query: 'true' - port: - entity: - mappings: - - identifier: .Id - title: .Name - blueprint: '"awsAccount"' - properties: - arn: .Arn - email: .Email - status: .Status - joined_method: .JoinedMethod - joined_timestamp: .JoinedTimestamp | sub(" "; "T") - account_id: .Id - relations: - organization: .__OrganizationId - -# Cross-Account S3 Buckets -- kind: AWS::S3::Bucket - selector: - query: 'true' - useGetResourceAPI: 'true' - port: - entity: - mappings: - - identifier: .Identifier - title: .Identifier - blueprint: '"s3Bucket"' - properties: - kind: .__Kind - region: .Properties.RegionalDomainName | capture(".*\\.(?[^\\.]+)\\.amazonaws\\.com") | .region - account_id: .__AccountId - creation_date: .Properties.CreationDate - tags: .Properties.Tags - arn: .Properties.Arn - environment: .Properties.Tags.Environment // "unknown" - project: .Properties.Tags.Project // "unknown" - cost_center: .Properties.Tags.CostCenter // "unknown" - link: .Properties | select(.Arn != null) | "https://console.aws.amazon.com/go/view?arn=" + .Arn - relations: - account: .__AccountId -``` - -## Filtering Examples - -### Environment-Based Filtering - -Filter resources by environment tags: - -```yaml showLineNumbers -resources: -- kind: AWS::EC2::Instance - selector: - query: '.Properties.Tags | select(.Key == "Environment") | .Value == "production"' - port: - entity: - mappings: - - identifier: .Identifier - title: .Identifier - blueprint: '"ec2Instance"' - properties: - kind: .__Kind - region: .__Region - account_id: .__AccountId - instance_type: .Properties.InstanceType - state: .Properties.State.Name - environment: .Properties.Tags | select(.Key == "Environment") | .Value - project: .Properties.Tags | select(.Key == "Project") | .Value - tags: .Properties.Tags - arn: .Properties.Arn - relations: - account: .__AccountId - -- kind: AWS::S3::Bucket - selector: - query: '.Properties.Tags | select(.Key == "Environment") | .Value == "production"' - port: - entity: - mappings: - - identifier: .Identifier - title: .Identifier - blueprint: '"s3Bucket"' - properties: - kind: .__Kind - region: .Properties.RegionalDomainName | capture(".*\\.(?[^\\.]+)\\.amazonaws\\.com") | .region - account_id: .__AccountId - environment: .Properties.Tags | select(.Key == "Environment") | .Value - project: .Properties.Tags | select(.Key == "Project") | .Value - tags: .Properties.Tags - arn: .Properties.Arn - relations: - account: .__AccountId -``` - -### Resource Type Filtering - -Filter specific resource types: - -```yaml showLineNumbers -resources: -# Only t3.micro instances -- kind: AWS::EC2::Instance - selector: - query: '.Properties.InstanceType == "t3.micro"' - port: - entity: - mappings: - - identifier: .Identifier - title: .Identifier - blueprint: '"ec2Instance"' - properties: - kind: .__Kind - region: .__Region - account_id: .__AccountId - instance_type: .Properties.InstanceType - state: .Properties.State.Name - tags: .Properties.Tags - arn: .Properties.Arn - relations: - account: .__AccountId - -# Only t3.micro instances -- kind: AWS::EC2::Instance - selector: - query: '.Properties.InstanceType == "t3.micro"' - port: - entity: - mappings: - - identifier: .Identifier - title: .Identifier - blueprint: '"ec2Instance"' - properties: - kind: .__Kind - region: .__Region - account_id: .__AccountId - instance_type: .Properties.InstanceType - state: .Properties.State.Name - tags: .Properties.Tags - arn: .Properties.Arn - relations: - account: .__AccountId -``` - -## Complex Relationship Examples - -### ECS Cluster and Service Relationships - -Map ECS clusters and their services with relationships: - -```yaml showLineNumbers -resources: -# ECS Clusters -- kind: AWS::ECS::Cluster - selector: - query: 'true' - useGetResourceAPI: 'true' - port: - entity: - mappings: - - identifier: .Properties.ClusterArn - title: .Properties.ClusterName - blueprint: '"ecsCluster"' - properties: - kind: .__Kind - region: .__Region - account_id: .__AccountId - cluster_name: .Properties.ClusterName - status: .Properties.Status - running_tasks_count: .Properties.RunningTasksCount - pending_tasks_count: .Properties.PendingTasksCount - active_services_count: .Properties.ActiveServicesCount - capacity_providers: .Properties.CapacityProviders - tags: .Properties.Tags - arn: .Properties.ClusterArn - link: .Properties | select(.Arn != null) | "https://console.aws.amazon.com/go/view?arn=" + .Arn - relations: - account: .__AccountId - -# ECS Services -- kind: AWS::ECS::Service - selector: - query: 'true' - useGetResourceAPI: 'true' - port: - entity: - mappings: - - identifier: .Properties.ServiceArn - title: .Properties.ServiceName - blueprint: '"ecsService"' - properties: - kind: .__Kind - region: .__Region - account_id: .__AccountId - service_name: .Properties.ServiceName - cluster_arn: .Properties.ClusterArn - task_definition: .Properties.TaskDefinition - desired_count: .Properties.DesiredCount - running_count: .Properties.RunningCount - pending_count: .Properties.PendingCount - launch_type: .Properties.LaunchType - platform_version: .Properties.PlatformVersion - status: .Properties.Status - tags: .Properties.Tags - arn: .Properties.ServiceArn - link: .Properties | select(.Arn != null) | "https://console.aws.amazon.com/go/view?arn=" + .Arn - relations: - account: .__AccountId - cluster: .Properties.ClusterArn -``` - -## Performance Optimization Examples - -### Parallel Processing Configuration - -Configure the integration for optimal performance: - -```yaml showLineNumbers -# Performance configuration -performance: - parallel_processing: - enabled: true - max_concurrent_requests: 10 - max_concurrent_accounts: 5 - - caching: - enabled: true - cache_ttl: "1h" - cache_size: 1000 - - rate_limiting: - enabled: true - requests_per_second: 10 - burst_limit: 20 - -aws: - access_key_id: "YOUR_ACCESS_KEY" - secret_access_key: "YOUR_SECRET_KEY" - region: "us-east-1" - - # Enable performance optimizations - optimizations: - use_get_resource_api: true - parallel_discovery: true - smart_caching: true - -resources: - - kind: AWS::S3::Bucket - selector: - query: 'true' - useGetResourceAPI: 'true' - port: - entity: - mappings: - - identifier: .Identifier - title: .Identifier - blueprint: '"s3Bucket"' - properties: - kind: .__Kind - region: .Properties.RegionalDomainName | capture(".*\\.(?[^\\.]+)\\.amazonaws\\.com") | .region - account_id: .__AccountId - tags: .Properties.Tags - arn: .Properties.Arn - relations: - account: .__AccountId -``` - -## Error Handling Examples - -### Robust Error Handling - -Configure comprehensive error handling: - -```yaml showLineNumbers -# Error handling configuration -error_handling: - retry_policy: - max_retries: 3 - retry_delay: "5s" - exponential_backoff: true - - error_notification: - enabled: true - webhook_url: "https://your-webhook-url.com/errors" - email_notifications: ["admin@yourcompany.com"] - - fallback_behavior: - skip_failed_resources: true - continue_on_error: true - log_errors: true - -aws: - access_key_id: "YOUR_ACCESS_KEY" - secret_access_key: "YOUR_SECRET_KEY" - region: "us-east-1" - -resources: - - kind: AWS::S3::Bucket - selector: - query: 'true' - useGetResourceAPI: 'true' - port: - entity: - mappings: - - identifier: .Identifier - title: .Identifier - blueprint: '"s3Bucket"' - properties: - kind: .__Kind - region: .Properties.RegionalDomainName | capture(".*\\.(?[^\\.]+)\\.amazonaws\\.com") | .region - account_id: .__AccountId - tags: .Properties.Tags - arn: .Properties.Arn - # Add error handling for missing properties - creation_date: .Properties.CreationDate // "unknown" - versioning: .Properties.Versioning.Status // "unknown" - relations: - account: .__AccountId -``` - -## Custom Blueprint Examples - -### Custom Resource Blueprints - -Create custom blueprints for specific use cases: - -```yaml showLineNumbers -resources: -# Custom Application Blueprint -- kind: AWS::ECS::Service - selector: - query: 'true' - useGetResourceAPI: 'true' - port: - entity: - mappings: - - identifier: .Properties.ServiceArn - title: .Properties.ServiceName - blueprint: '"application"' - properties: - name: .Properties.ServiceName - type: '"microservice"' - environment: .Properties.Tags.Environment // "unknown" - team: .Properties.Tags.Team // "unknown" - cost_center: .Properties.Tags.CostCenter // "unknown" - status: .Properties.Status - desired_count: .Properties.DesiredCount - running_count: .Properties.RunningCount - cluster: .Properties.ClusterArn - task_definition: .Properties.TaskDefinition - launch_type: .Properties.LaunchType - tags: .Properties.Tags - arn: .Properties.ServiceArn - link: .Properties | select(.Arn != null) | "https://console.aws.amazon.com/go/view?arn=" + .Arn - relations: - account: .__AccountId - cluster: .Properties.ClusterArn - -# Custom Database Blueprint -- kind: AWS::RDS::DBInstance - selector: - query: 'true' - useGetResourceAPI: 'true' - port: - entity: - mappings: - - identifier: .Properties.DBInstanceIdentifier - title: .Properties.DBInstanceIdentifier - blueprint: '"database"' - properties: - name: .Properties.DBInstanceIdentifier - type: '"relational"' - engine: .Properties.Engine - version: .Properties.EngineVersion - environment: .Properties.TagList | select(.Key == "Environment") | .Value // "unknown" - team: .Properties.TagList | select(.Key == "Team") | .Value // "unknown" - cost_center: .Properties.TagList | select(.Key == "CostCenter") | .Value // "unknown" - status: .Properties.DBInstanceStatus - instance_class: .Properties.DBInstanceClass - allocated_storage: .Properties.AllocatedStorage - multi_az: .Properties.MultiAZ - backup_retention: .Properties.BackupRetentionPeriod - tags: .Properties.TagList - arn: .Properties.DBInstanceArn - link: .Properties | select(.DBInstanceArn != null) | "https://console.aws.amazon.com/go/view?arn=" + .DBInstanceArn - relations: - account: .__AccountId -``` - -## Testing and Validation - -### Configuration Validation - -Test your configuration before deployment: - -```bash showLineNumbers -# Validate configuration syntax -python -c "import yaml; yaml.safe_load(open('config.yaml'))" - -# Test resource discovery -python main.py --dry-run --config config.yaml - -# Validate mapping syntax -python main.py --validate-mappings --config config.yaml -``` - -### Performance Testing - -Test performance with different configurations: - -```bash showLineNumbers -# Test with small resource set -python main.py --config config-small.yaml --benchmark - -# Test with full resource set -python main.py --config config-full.yaml --benchmark - -# Compare performance -python benchmark.py --config1 config-small.yaml --config2 config-full.yaml -``` - -## Best Practices - -### 1. Resource Selection - -- Use specific resource kinds instead of broad queries -- Implement proper filtering to reduce API calls -- Use `useGetResourceAPI: 'true'` when available - -### 2. Performance Optimization - -- Enable parallel processing for large deployments -- Use caching for frequently accessed resources -- Implement rate limiting to respect AWS limits - -### 3. Error Handling - -- Implement comprehensive error handling -- Use fallback values for missing properties -- Set up monitoring and alerting - -### 4. Security - -- Use least privilege IAM policies -- Encrypt sensitive configuration data -- Implement proper access controls - -### 5. Maintenance - -- Regular configuration reviews -- Monitor performance metrics -- Update configurations as AWS services evolve From 6c1dcb21b1334de27fbe740b839ca7340baae168 Mon Sep 17 00:00:00 2001 From: Shalev Avhar Date: Mon, 8 Sep 2025 14:05:47 +0300 Subject: [PATCH 09/16] docs: Add IAM Role Architecture guide and update installation documentation - Introduced a new guide detailing the IAM role architecture for AWS Hosted by Port, explaining its structure, permissions, and security features. - Updated the installation documentation to include a link to the new IAM Role Architecture guide for better user understanding of the integration's security model. --- .../cloud-providers/aws-v3/aws-v3.md | 2 + .../installations/iam-role-architecture.md | 131 ++++++++++++++++++ .../aws-v3/installations/installations.md | 2 + 3 files changed, 135 insertions(+) create mode 100644 docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/installations/iam-role-architecture.md diff --git a/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/aws-v3.md b/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/aws-v3.md index 0989697a38..e1638155eb 100644 --- a/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/aws-v3.md +++ b/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/aws-v3.md @@ -69,6 +69,8 @@ AWS Hosted by Port provides several advantages over the standard AWS integration Continue to the [installation](./installations/installations.md) guide to learn how to install AWS Hosted by Port. +For detailed information about the IAM role architecture and security model, see the [IAM Role Architecture](./installations/iam-role-architecture.md) guide. + ## Configuration diff --git a/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/installations/iam-role-architecture.md b/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/installations/iam-role-architecture.md new file mode 100644 index 0000000000..965488ebdf --- /dev/null +++ b/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/installations/iam-role-architecture.md @@ -0,0 +1,131 @@ +--- +sidebar_position: 2 +--- + +# IAM Role Architecture + +This page explains how the AWS Hosted by Port IAM role is constructed and what permissions it grants to the integration. + +## Overview + +AWS Hosted by Port uses a strategically designed IAM role that provides comprehensive read-only access to all AWS services. The role is created automatically by the CloudFormation template and uses the AWS managed `ReadOnlyAccess` policy for future-proofing and operational simplicity. + +## Role Structure + +### OIDC Identity Provider + +The CloudFormation template creates an OIDC identity provider that connects to Port's EKS cluster: + +```yaml +PortIntegrationOIDCProvider: + Type: AWS::IAM::OIDCProvider + Properties: + Url: 'https://oidc.eks.eu-west-1.amazonaws.com/id/56E5F51C07138118A9183ECEAA68FAF4' + ClientIdList: + - sts.amazonaws.com + Tags: + - Key: port:integration + Value: !Ref IntegrationIdentifier +``` + +**Key Details**: +- **EKS OIDC URL**: Points to Port's production EKS cluster in EU-West-1 +- **Client ID**: Uses `sts.amazonaws.com` for IRSA authentication +- **Reusable**: Can be shared across multiple integrations in the same account +- **Optional**: Can be disabled if you already have a Port OIDC provider + +### Trust Policy + +The IAM role uses an **OIDC (OpenID Connect) trust policy** with **IRSA (IAM Roles for Service Accounts)** that allows Port's EKS cluster to assume the role: + +```json +{ + "Version": "2012-10-17", + "Statement": [{ + "Effect": "Allow", + "Principal": { + "Federated": "arn:aws:iam::YOUR_ACCOUNT_ID:oidc-provider/oidc.eks.eu-west-1.amazonaws.com/id/56E5F51C07138118A9183ECEAA68FAF4" + }, + "Action": "sts:AssumeRoleWithWebIdentity", + "Condition": { + "StringEquals": { + "oidc.eks.eu-west-1.amazonaws.com/id/56E5F51C07138118A9183ECEAA68FAF4:aud": "sts.amazonaws.com", + "oidc.eks.eu-west-1.amazonaws.com/id/56E5F51C07138118A9183ECEAA68FAF4:sub": "system:serviceaccount:org-YOUR_ORG_ID-port-oidc-sa" + } + } + }] +} +``` + +**Key Security Features**: +- **IRSA Authentication**: Uses EKS service account-based authentication +- **Audience Validation**: Only AWS STS service can assume the role +- **Subject Validation**: Role is tied to Port's specific EKS service account +- **Temporary Credentials**: All access uses short-lived tokens (typically 1 hour) + +### Permissions Policy + +The role uses the **AWS managed `ReadOnlyAccess` policy**, which provides comprehensive read-only access to all AWS services: + +```yaml +ManagedPolicyArns: + - arn:aws:iam::aws:policy/ReadOnlyAccess +``` + +**Strategic Benefits**: +- **Future-Proof**: Automatically includes new AWS services without CloudFormation updates +- **Operational Simplicity**: No need to redeploy when adding support for new services +- **Comprehensive Coverage**: Access to all AWS services with read-only permissions +- **AWS Maintained**: AWS manages and updates the policy as needed +- **Read-Only Security**: Only read permissions, no write/delete/create access + +## Permission Categories + +Since the role uses the AWS managed `ReadOnlyAccess` policy, it has comprehensive read-only access to **all AWS services**. Here are the key categories relevant to AWS Hosted by Port: + +### What This Enables +- **Comprehensive Discovery**: Access to all AWS resource types +- **Future-Proof**: New services are automatically supported without redeployment +- **Operational Efficiency**: No CloudFormation updates needed when adding new services +- **Consistent Access**: Same permission model across all services +- **No Maintenance**: AWS manages policy updates + +## Security Considerations + +### What the Integration CAN Do +- ✅ **Read resource metadata** and configuration +- ✅ **List resources** across supported services +- ✅ **Access resource tags** for categorization +- ✅ **Read security settings** (ACLs, policies, etc.) +- ✅ **Discover account structure** (for multi-account setups) + +### What the Integration CANNOT Do +- ❌ **Modify any resources** (no write permissions) +- ❌ **Delete resources** (no delete permissions) +- ❌ **Change security settings** (no policy modification) +- ❌ **Create new resources** (no create permissions) +- ❌ **Access other AWS accounts** (unless explicitly configured) + +## Multi-Account Role Structure + +For multi-account setups, the role structure is replicated across all target accounts + +## Role Modifications + +:::info Keeping the Role Unchanged +We recommend keeping the IAM role and its permissions unchanged after deployment. The integration is designed to work with the full `ReadOnlyAccess` policy, which ensures: + +- **Complete resource discovery** across all AWS services +- **Future compatibility** when Port adds support for new AWS services +- **Reliable operation** without permission-related issues + +If you need to restrict access to specific resources, consider using AWS resource-level permissions or contact your Port representative for guidance on alternative approaches. +::: + +## Support and Resources + +- **CloudFormation Template**: [Single Account Template](https://port-cloudformation-templates.s3.eu-west-1.amazonaws.com/stable/ocean/aws-v3/single-account-integration.yaml) +- **CloudFormation Template**: [Multi-Account Template](https://port-cloudformation-templates.s3.eu-west-1.amazonaws.com/stable/ocean/aws-v3/multi-account-integration.yaml) +- **AWS IAM Documentation**: [IAM Roles](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles.html) +- **IRSA Documentation**: [IAM Roles for Service Accounts](https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html) +- **OIDC Documentation**: [AWS OIDC Identity Providers](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_create_oidc.html) diff --git a/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/installations/installations.md b/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/installations/installations.md index 1b5e1dad3b..937f5f222d 100644 --- a/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/installations/installations.md +++ b/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/installations/installations.md @@ -98,6 +98,8 @@ For a single AWS account, you'll deploy a CloudFormation stack that creates the :::tip Why Can't I Use an Existing Role? AWS Hosted by Port requires specific OIDC trust relationships and permissions that are automatically configured by the CloudFormation template. Using an existing role would require manual configuration of these complex trust relationships, which is why we provide the CloudFormation template to ensure proper setup. + +**Learn More**: For detailed information about the IAM role architecture and permissions, see the [IAM Role Architecture](./iam-role-architecture.md) guide. ::: From b2de64b8b87631e3c23c35e75eaa2ac3375470df Mon Sep 17 00:00:00 2001 From: Sivan Elkabes Date: Tue, 9 Sep 2025 16:41:10 +0300 Subject: [PATCH 10/16] updated the new integration pages --- .../cloud-providers/aws-v3/aws-v3.md | 174 ++--------------- .../installations/iam-role-architecture.md | 109 ++++------- .../aws-v3/installations/installations.md | 180 ++++++++---------- 3 files changed, 129 insertions(+), 334 deletions(-) diff --git a/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/aws-v3.md b/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/aws-v3.md index e1638155eb..069ed54803 100644 --- a/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/aws-v3.md +++ b/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/aws-v3.md @@ -17,11 +17,7 @@ Port's AWS Hosted by Port integration allows you to import your AWS resources in The integration periodically syncs your AWS resources to ensure your Port catalog stays up-to-date with your AWS infrastructure. -:::tip -AWS Hosted by Port is fully managed by Port - no maintenance, updates, or infrastructure management required on your end. -::: - -## 💡 AWS Hosted by Port common use cases +## Common use cases Easily fill your software catalog with data directly from your AWS Organization, for example: @@ -30,26 +26,12 @@ Easily fill your software catalog with data directly from your AWS Organization, - Use relations to create complete, easily digestible views of your AWS infrastructure inside Port. - Enjoy a fully managed experience with no infrastructure to maintain or updates to apply. -## How it works - -AWS Hosted by Port connects to your AWS accounts using **OIDC (OpenID Connect)** authentication to securely access your AWS resources: - -### Single Account Setup -1. **Role Assumption**: The integration assumes the IAM role you create in your AWS account -2. **Resource Discovery**: It discovers and exports your AWS resources to Port -3. **Periodic Sync**: The integration periodically syncs to keep your Port catalog up-to-date - -### Multi-Account Setup -1. **Organization Access**: The integration connects to your AWS Organizations master account -2. **Account Discovery**: It lists all member accounts in your organization -3. **Cross-Account Access**: For each account, it assumes the appropriate IAM role -4. **Resource Export**: It exports resources from all accounts to Port -5. **Periodic Sync**: The integration periodically syncs across all accounts +## Supported resources The integration currently supports the following AWS resource types: -- **S3 Buckets**: Complete bucket information including properties, tags, and metadata -- **ECS Clusters**: Cluster details, services, and task definitions -- **EC2 Instances**: Instance information, security groups, and networking details +- `S3 Buckets`: Complete bucket information including properties, tags, and metadata. +- `ECS Clusters`: Cluster details, services, and task definitions. +- `EC2 Instances`: Instance information, security groups, and networking details. :::info More Resource Types Coming Soon We're actively working on adding support for additional AWS resource types to provide comprehensive coverage of your AWS infrastructure. @@ -59,11 +41,11 @@ We're actively working on adding support for additional AWS resource types to pr AWS Hosted by Port provides several advantages over the standard AWS integration: -- **Fully Hosted**: No infrastructure to maintain, update, or monitor -- **Simplified Installation**: Just deploy CloudFormation templates to create IAM roles -- **Complete Data**: Ensures no missing or incomplete resource information -- **Periodic Sync**: Regular updates to keep your catalog current -- **Zero Maintenance**: Port handles all updates, scaling, and infrastructure management +- **Fully Hosted**: No infrastructure to maintain, update, or monitor. +- **Simplified Installation**: Just deploy CloudFormation templates to create IAM roles. +- **Complete Data**: Ensures no missing or incomplete resource information. +- **Periodic Sync**: Regular updates to keep your catalog current. +- **Zero Maintenance**: Port handles all updates, scaling, and infrastructure management. ## Getting started @@ -71,7 +53,6 @@ Continue to the [installation](./installations/installations.md) guide to learn For detailed information about the IAM role architecture and security model, see the [IAM Role Architecture](./installations/iam-role-architecture.md) guide. - ## Configuration Port integrations use a [YAML mapping block](/build-your-software-catalog/customize-integrations/configure-mapping#configuration-structure) to ingest data from the third-party api into Port. @@ -207,137 +188,4 @@ resources: - - -## Advanced Configuration - -### AWS SDK v3 Specific Features - -The AWS Hosted by Port integration leverages several AWS SDK v3 specific features: - -- **Modular Architecture**: Only imports the specific AWS services you need, reducing bundle size -- **Enhanced TypeScript Support**: Full TypeScript support with better type inference -- **Improved Error Handling**: More granular error types and better error messages -- **Better Performance**: Optimized for performance with reduced memory footprint - -### Resource Discovery Optimization - -The AWS Hosted by Port integration includes several optimizations for resource discovery: - -- **Parallel Processing**: Processes multiple regions and services in parallel -- **Smart Caching**: Implements intelligent caching to reduce API calls -- **Rate Limiting**: Built-in rate limiting to respect AWS API limits -- **Retry Logic**: Enhanced retry logic with exponential backoff - -### Configuration Examples - -#### Basic Configuration - -```yaml showLineNumbers -resources: -- kind: AWS::S3::Bucket - selector: - query: 'true' - useGetResourceAPI: 'true' - port: - entity: - mappings: - identifier: .Identifier - title: .Identifier - blueprint: '"s3Bucket"' - properties: - region: .Properties.RegionalDomainName | capture(".*\\.(?[^\\.]+)\\.amazonaws\\.com") | .region - tags: .Properties.Tags - arn: .Properties.Arn -``` - -#### Advanced Configuration with Relations - -```yaml showLineNumbers -resources: -- kind: AWS::ECS::Service - selector: - query: 'true' - useGetResourceAPI: 'true' - port: - entity: - mappings: - identifier: .Properties.ServiceArn - title: .Properties.ServiceName - blueprint: '"ecsService"' - properties: - cluster: .Properties.ClusterArn - desired_count: .Properties.DesiredCount - running_count: .Properties.RunningCount - tags: .Properties.Tags - arn: .Properties.ServiceArn - relations: - cluster: .Properties.ClusterArn - account: .__AccountId -``` - -## Troubleshooting - -### Common Issues - -#### AWS SDK v3 Compatibility - -If you encounter compatibility issues with AWS SDK v3: - -1. Ensure you're using the latest version of the AWS Hosted by Port integration -2. Check that your AWS credentials are properly configured -3. Verify that the required AWS services are available in your region - -#### Performance Issues - -For performance optimization: - -1. Use the `useGetResourceAPI: 'true'` flag for resources that support it -2. Implement proper filtering in your selector queries -3. Consider using parallel processing for large-scale deployments - -#### Memory Usage - -To optimize memory usage: - -1. Use specific resource kinds instead of broad queries -2. Implement proper pagination for large datasets -3. Monitor memory usage and adjust configuration accordingly - -### Debug Mode - -Enable debug mode for detailed logging: - -```yaml showLineNumbers -debug: true -log_level: "DEBUG" -``` - -This will provide detailed information about: -- API calls being made -- Resource processing status -- Error details and stack traces -- Performance metrics - -## Migration from AWS Integration - -If you're migrating from the standard AWS integration to AWS Hosted by Port: - -1. **Backup Configuration**: Save your current configuration -2. **Update Mapping**: Review and update your mapping configuration if needed -3. **Test Integration**: Test the new integration in a development environment -4. **Deploy**: Deploy to production once testing is complete - -### Configuration Changes - -The main differences in configuration: - -- Enhanced error handling options -- Additional performance tuning parameters -- Improved resource discovery settings -- Better support for complex resource relationships - -## Support and Resources - -- **Community**: [Port Community Forum](https://github.com/port-labs/port/discussions) -- **Issues**: [Report Issues](https://github.com/port-labs/ocean/issues) + \ No newline at end of file diff --git a/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/installations/iam-role-architecture.md b/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/installations/iam-role-architecture.md index 965488ebdf..cd46f118f4 100644 --- a/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/installations/iam-role-architecture.md +++ b/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/installations/iam-role-architecture.md @@ -2,21 +2,28 @@ sidebar_position: 2 --- -# IAM Role Architecture +# IAM role architecture -This page explains how the AWS Hosted by Port IAM role is constructed and what permissions it grants to the integration. +AWS Hosted by Port uses a strategically designed IAM role that provides comprehensive read-only access to all AWS services. The role is created automatically by the CloudFormation template and uses the AWS managed `ReadOnlyAccess` policy for future-proofing and operational simplicity. -## Overview +:::warning Role modifications +We recommend keeping the IAM role and its permissions unchanged after deployment. +The integration is designed to work with the full `ReadOnlyAccess` policy, which ensures: -AWS Hosted by Port uses a strategically designed IAM role that provides comprehensive read-only access to all AWS services. The role is created automatically by the CloudFormation template and uses the AWS managed `ReadOnlyAccess` policy for future-proofing and operational simplicity. +- **Complete resource discovery** across all AWS services. +- **Future compatibility** when Port adds support for new AWS services. +- **Reliable operation** without permission-related issues. +::: + +## Role structure -## Role Structure +For multi-account setups, the role structure is replicated across all target accounts. -### OIDC Identity Provider +### OIDC identity provider The CloudFormation template creates an OIDC identity provider that connects to Port's EKS cluster: -```yaml +```yaml showLineNumbers PortIntegrationOIDCProvider: Type: AWS::IAM::OIDCProvider Properties: @@ -29,16 +36,16 @@ PortIntegrationOIDCProvider: ``` **Key Details**: -- **EKS OIDC URL**: Points to Port's production EKS cluster in EU-West-1 -- **Client ID**: Uses `sts.amazonaws.com` for IRSA authentication -- **Reusable**: Can be shared across multiple integrations in the same account -- **Optional**: Can be disabled if you already have a Port OIDC provider +- **EKS OIDC URL**: Points to Port's production EKS cluster in EU-West-1. +- **Client ID**: Uses `sts.amazonaws.com` for IRSA authentication. +- **Reusable**: Can be shared across multiple integrations in the same account. +- **Optional**: Can be disabled if you already have a Port OIDC provider. -### Trust Policy +### Trust policy The IAM role uses an **OIDC (OpenID Connect) trust policy** with **IRSA (IAM Roles for Service Accounts)** that allows Port's EKS cluster to assume the role: -```json +```json showLineNumbers { "Version": "2012-10-17", "Statement": [{ @@ -58,12 +65,12 @@ The IAM role uses an **OIDC (OpenID Connect) trust policy** with **IRSA (IAM Rol ``` **Key Security Features**: -- **IRSA Authentication**: Uses EKS service account-based authentication -- **Audience Validation**: Only AWS STS service can assume the role -- **Subject Validation**: Role is tied to Port's specific EKS service account -- **Temporary Credentials**: All access uses short-lived tokens (typically 1 hour) +- **IRSA Authentication**: Uses EKS service account-based authentication. +- **Audience Validation**: Only AWS STS service can assume the role. +- **Subject Validation**: Role is tied to Port's specific EKS service account. +- **Temporary Credentials**: All access uses short-lived tokens (typically 1 hour). -### Permissions Policy +### Permissions policy The role uses the **AWS managed `ReadOnlyAccess` policy**, which provides comprehensive read-only access to all AWS services: @@ -73,59 +80,23 @@ ManagedPolicyArns: ``` **Strategic Benefits**: -- **Future-Proof**: Automatically includes new AWS services without CloudFormation updates -- **Operational Simplicity**: No need to redeploy when adding support for new services -- **Comprehensive Coverage**: Access to all AWS services with read-only permissions -- **AWS Maintained**: AWS manages and updates the policy as needed -- **Read-Only Security**: Only read permissions, no write/delete/create access - -## Permission Categories - -Since the role uses the AWS managed `ReadOnlyAccess` policy, it has comprehensive read-only access to **all AWS services**. Here are the key categories relevant to AWS Hosted by Port: - -### What This Enables -- **Comprehensive Discovery**: Access to all AWS resource types -- **Future-Proof**: New services are automatically supported without redeployment -- **Operational Efficiency**: No CloudFormation updates needed when adding new services -- **Consistent Access**: Same permission model across all services -- **No Maintenance**: AWS manages policy updates +- **Future-Proof**: Automatically includes new AWS services without CloudFormation updates. +- **Operational Simplicity**: No need to redeploy when adding support for new services. +- **Comprehensive Coverage**: Access to all AWS services with read-only permissions. +- **AWS Maintained**: AWS manages and updates the policy as needed. +- **Read-Only Security**: Only read permissions, no write/delete/create access. -## Security Considerations +## Permission categories -### What the Integration CAN Do -- ✅ **Read resource metadata** and configuration -- ✅ **List resources** across supported services -- ✅ **Access resource tags** for categorization -- ✅ **Read security settings** (ACLs, policies, etc.) -- ✅ **Discover account structure** (for multi-account setups) +Since the role uses the AWS managed `ReadOnlyAccess` policy, it has comprehensive read-only access to **all AWS services**. +Here are the key categories relevant to AWS Hosted by Port: -### What the Integration CANNOT Do -- ❌ **Modify any resources** (no write permissions) -- ❌ **Delete resources** (no delete permissions) -- ❌ **Change security settings** (no policy modification) -- ❌ **Create new resources** (no create permissions) -- ❌ **Access other AWS accounts** (unless explicitly configured) - -## Multi-Account Role Structure - -For multi-account setups, the role structure is replicated across all target accounts - -## Role Modifications - -:::info Keeping the Role Unchanged -We recommend keeping the IAM role and its permissions unchanged after deployment. The integration is designed to work with the full `ReadOnlyAccess` policy, which ensures: - -- **Complete resource discovery** across all AWS services -- **Future compatibility** when Port adds support for new AWS services -- **Reliable operation** without permission-related issues - -If you need to restrict access to specific resources, consider using AWS resource-level permissions or contact your Port representative for guidance on alternative approaches. -::: +- **Comprehensive Discovery**: Access to all AWS resource types. +- **Future-Proof**: New services are automatically supported without redeployment. +- **Operational Efficiency**: No CloudFormation updates needed when adding new services. +- **Consistent Access**: Same permission model across all services. +- **No Maintenance**: AWS manages policy updates. -## Support and Resources +## Security considerations -- **CloudFormation Template**: [Single Account Template](https://port-cloudformation-templates.s3.eu-west-1.amazonaws.com/stable/ocean/aws-v3/single-account-integration.yaml) -- **CloudFormation Template**: [Multi-Account Template](https://port-cloudformation-templates.s3.eu-west-1.amazonaws.com/stable/ocean/aws-v3/multi-account-integration.yaml) -- **AWS IAM Documentation**: [IAM Roles](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles.html) -- **IRSA Documentation**: [IAM Roles for Service Accounts](https://docs.aws.amazon.com/eks/latest/userguide/iam-roles-for-service-accounts.html) -- **OIDC Documentation**: [AWS OIDC Identity Providers](https://docs.aws.amazon.com/IAM/latest/UserGuide/id_roles_providers_create_oidc.html) +From a security view point the integration uses a **read-only** role. It can list/describe and read metadata/tags, but cannot create, modify, delete, or change policies. No cross-account access is available unless it is explicitly configured. \ No newline at end of file diff --git a/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/installations/installations.md b/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/installations/installations.md index 937f5f222d..6dc8d0828b 100644 --- a/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/installations/installations.md +++ b/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/installations/installations.md @@ -7,39 +7,25 @@ import TabItem from "@theme/TabItem"; # Installation -This guide will walk you through installing AWS Hosted by Port in your Port environment. - -## Installation Process - -AWS Hosted by Port is available through **Port's Ocean SaaS platform**. The installation process is simple - you only need to create IAM roles in your AWS accounts to grant the integration access to read your resources. The integration handles everything else automatically. - -:::info How the Integration Works -AWS Hosted by Port runs on **Port's servers** and connects to your AWS accounts using **OIDC (OpenID Connect)** authentication. Here's how it works: - -1. **You create IAM roles** in your AWS accounts using our CloudFormation templates -2. **Port's servers assume these roles** using OIDC to get temporary AWS credentials -3. **Port discovers your AWS resources** by calling AWS APIs with the assumed roles -4. **Port exports the resources** to your Port account in the software catalog -5. **Port periodically syncs** to keep your catalog up-to-date with your AWS infrastructure -::: - :::warning Beta Access Required AWS Hosted by Port is currently in beta mode. Contact your Port representative to request access to this integration before proceeding with installation. ::: -## Supported AWS Resources +AWS Hosted by Port is available through **Port's Ocean SaaS platform**. -AWS Hosted by Port currently supports the following AWS resource types: +The installation process is simple - you only need to create IAM roles in your AWS accounts to grant the integration access to read your resources. The integration handles everything else automatically. -- **S3 Buckets**: Complete bucket information including properties, tags, and metadata -- **ECS Clusters**: Cluster details, services, and task definitions -- **EC2 Instances**: Instance information, security groups, and networking details +**How the integration works:** -:::info More Resource Types Coming Soon -We're actively working on adding support for additional AWS resource types to provide comprehensive coverage of your AWS infrastructure. -::: +AWS Hosted by Port runs on **Port's servers** and connects to your AWS accounts using **OIDC (OpenID Connect)** authentication. Here's how it works: + +1. **You create IAM roles** in your AWS accounts using our CloudFormation templates. +2. **Port's servers assume these roles** using OIDC to get temporary AWS credentials. +3. **Port discovers your AWS resources** by calling AWS APIs with the assumed roles. +4. **Port exports the resources** to your Port account in the software catalog. +5. **Port periodically syncs** to keep your catalog up-to-date with your AWS infrastructure. -## Installation Methods +## Installation methods -### Single Account Installation - For a single AWS account, you'll deploy a CloudFormation stack that creates the necessary IAM roles. -#### Step 1: Access AWS Console +

Step 1: Access AWS Console

-1. **Log into your AWS account**: - - Go to [AWS Console](https://console.aws.amazon.com/) - - Sign in with your AWS account credentials +- **Log into your AWS account**: + - Go to [AWS Console](https://console.aws.amazon.com/). + - Sign in with your AWS account credentials. -#### Step 2: Deploy CloudFormation Stack +

Step 2: Deploy CloudFormation Stack

-1. **Access the CloudFormation Template**: - - Go to [Port Data Sources](https://app.getport.io/settings/data-sources) - - Click **+ Add Integration** → **AWS Hosted by Port** - - Select **Single Account** and click the **"Click here"** link in step 3 - - This will open CloudFormation with pre-configured parameters +- **Access the CloudFormation Template**: + - Go to [Port Data Sources](https://app.getport.io/settings/data-sources). + - Click **+ Add Integration** → **AWS Hosted by Port**. + - Select **Single Account** and click the **"Click here"** link in step 3. + - This will open CloudFormation with pre-configured parameters. -2. **Deploy via AWS Console**: - - In the CloudFormation console, review the pre-configured parameters - - Scroll down to the bottom of the page - - Check the box **"I acknowledge that AWS CloudFormation might create IAM resources with custom names"** - - Click **Create Stack** +- **Deploy via AWS Console**: + - In the CloudFormation console, review the pre-configured parameters. + - Scroll down to the bottom of the page. + - Check the box **"I acknowledge that AWS CloudFormation might create IAM resources with custom names"**. + - Click **Create Stack**. -#### Step 3: Configure Integration in Port +

Step 3: Configure Integration in Port

-1. **Navigate to Port**: - - Go to your Port environment - - Navigate to **[Port Data Sources](https://app.getport.io/settings/data-sources)** +- **Navigate to Port**: + - Go to your Port environment. + - Navigate to **[Port Data Sources](https://app.getport.io/settings/data-sources)**. -2. **Add AWS Hosted by Port Integration**: - - Click **+ Add Integration** - - Select **AWS Hosted by Port** from the cloud providers section +- **Add AWS Hosted by Port Integration**: + - Click `+ Add Integration`. + - Select **AWS Hosted by Port** from the cloud providers section. -3. **Get the Role ARN**: - - After CloudFormation deployment completes, go to the **Outputs** tab - - Copy the **Role ARN** value +- **Get the Role ARN**: + - After CloudFormation deployment completes, go to the **Outputs** tab. + - Copy the **Role ARN** value. -4. **Complete Integration Setup**: - - Return to the Port integration form - - Paste the **Role ARN** into the **Account Role Arn** field - - Click **Done** +- **Complete Integration Setup**: + - Return to the Port integration form. + - Paste the **Role ARN** into the **Account Role Arn** field. + - Click `Done`. -5. **Verify Connection**: - - Port will automatically detect the IAM role created by CloudFormation - - The integration will start discovering your AWS resources +- **Verify Connection**: + - Port will automatically detect the IAM role created by CloudFormation. + - The integration will start discovering your AWS resources. :::tip Why Can't I Use an Existing Role? AWS Hosted by Port requires specific OIDC trust relationships and permissions that are automatically configured by the CloudFormation template. Using an existing role would require manual configuration of these complex trust relationships, which is why we provide the CloudFormation template to ensure proper setup. -**Learn More**: For detailed information about the IAM role architecture and permissions, see the [IAM Role Architecture](./iam-role-architecture.md) guide. +For detailed information about the IAM role architecture and permissions, see the [IAM Role Architecture](./iam-role-architecture.md) documentation. ::: -### Multi-Account Installation with AWS Organizations - For multiple AWS accounts, you'll use AWS Organizations and deploy the integration across multiple accounts using CloudFormation StackSets. -:::info Understanding AWS Organizations -- **Management Account**: The main account that manages your organization (also called "master account") -- **Member Accounts**: Individual AWS accounts in your organization -- **Organizational Units (OUs)**: Logical groupings of accounts (like folders in a file system) -- **OU IDs**: Unique identifiers for organizational units (format: `ou-abcd-12345678`) -- **Root**: The top-level container for all accounts and OUs (format: `r-xxxxxxxxx`) +

Understanding AWS Organizations

+ +- **Management Account**: The main account that manages your organization (also called "master account"). +- **Member Accounts**: Individual AWS accounts in your organization. +- **Organizational Units (OUs)**: Logical groupings of accounts (like folders in a file system). +- **OU IDs**: Unique identifiers for organizational units (format: `ou-abcd-12345678`). +- **Root**: The top-level container for all accounts and OUs (format: `r-xxxxxxxxx`). **Example Organization Structure**: ``` @@ -129,82 +112,77 @@ Root (r-123456789) └── Development OU (ou-dev-11223344) └── Account: dev (567890123456) ``` -::: -#### Step 1: Prepare Your Organization +

Step 1: Prepare Your Organization

-1. **Access Management Account**: +:::caution Management Account Access Required +You must run the multi-account installation from your AWS Organizations **management account**. This is because only the management account can deploy StackSets across member accounts. +::: + +- **Access Management Account**: - Log into your AWS Organizations management account - Navigate to [AWS Organizations](https://console.aws.amazon.com/organizations/) service -2. **Find Your OU IDs**: - - Go to **Organizational units** in the left sidebar - - Click on each organizational unit you want to target - - Copy the OU ID from the details page (format: `ou-abcd-12345678`) - - You can also target specific account IDs if needed +- **Find Your OU IDs**: + - In AWS Organizations, open **organizational units** in the left sidebar. + - Click an OU (e.g., **Production**). + - Copy the OU ID from the details page (format `ou-xxxx-xxxxxxxx`). + - Repeat for each OU you want to include. + - You can also target specific account IDs if needed. -:::tip Finding OU IDs -1. Go to AWS Organizations → Organizational units -2. Click on the OU name (e.g., "Production") -3. Copy the OU ID from the details (e.g., `ou-prod-12345678`) -4. Repeat for each OU you want to include +:::tip Common OU Naming Patterns Examples -**Common OU Naming Patterns**: - `ou-prod-12345678` (Production) - `ou-staging-87654321` (Staging) - `ou-dev-11223344` (Development) - `ou-shared-55667788` (Shared Services) ::: -:::caution Management Account Access Required -You must run the multi-account installation from your AWS Organizations **management account**. This is because only the management account can deploy StackSets across member accounts. -::: +

Step 2: Deploy Multi-Account CloudFormation Stack

-#### Step 2: Deploy Multi-Account CloudFormation Stack - -1. **Access the CloudFormation Template**: +- **Access the CloudFormation Template**: - Go to [Port Data Sources](https://app.getport.io/settings/data-sources) - Click **+ Add Integration** → **AWS Hosted by Port** - Select **Multiple Accounts** and click the **"Click here"** link in step 3 - This will open CloudFormation with pre-configured parameters -2. **Deploy via AWS Console**: +- **Deploy via AWS Console**: - In the CloudFormation console, review the pre-configured parameters - Scroll down to the bottom of the page - Check the box **"I acknowledge that AWS CloudFormation might create IAM resources with custom names"** - Click **Create Stack** -#### Step 3: Monitor Deployment +

Step 3: Monitor Deployment

-1. **Check StackSet Status**: +- **Check StackSet Status**: - Go to **CloudFormation** → **StackSets** in your management account - Monitor the deployment progress across all target accounts - Ensure all stack instances show "CREATE_COMPLETE" status -2. **Verify IAM Roles**: +- **Verify IAM Roles**: - Check that the IAM roles were created in each target account -#### Step 4: Configure Integration in Port +

Step 4: Configure Integration in Port

-1. **Navigate to Port**: +- **Navigate to Port**: - Go to your Port environment - Navigate to **[Port Data Sources](https://app.getport.io/settings/data-sources)** -2. **Add AWS Hosted by Port Integration**: +- **Add AWS Hosted by Port Integration**: - Click **+ Add Integration** - Select **AWS Hosted by Port** from the cloud providers section -3. **Get the Role ARN**: +- **Get the Role ARN**: - After CloudFormation deployment completes, go to the **Outputs** tab - Copy the **PortintegrationRoleArn** value -4. **Complete Integration Setup**: +- **Complete Integration Setup**: - Return to the Port integration form - Paste the **Management Account Role ARN** into the **Account Role Arn** field - Click **Done** -5. **Verify Multi-Account Connection**: +- **Verify Multi-Account Connection**: - Port will automatically detect the IAM roles across all accounts - The integration will start discovering resources from all configured accounts @@ -212,7 +190,7 @@ You must run the multi-account installation from your AWS Organizations **manage
-## Verify Installation +## Verify installation After installation, verify that the integration is working: @@ -229,9 +207,7 @@ After installation, verify that the integration is working: ## Troubleshooting -### Common Installation Issues - -#### CloudFormation Stack Creation Failures +Common Installation Issue - CloudFormation Stack Creation Failures. **Error**: `Stack creation failed: CREATE_FAILED` From 3e29e7337430a8d662cb0f757a8692afd41a5c29 Mon Sep 17 00:00:00 2001 From: Sivan Elkabes Date: Wed, 10 Sep 2025 12:06:44 +0300 Subject: [PATCH 11/16] Edited the installation explanation to fit the docs style --- .../aws-v3/installations/installations.md | 87 +++++++++---------- 1 file changed, 42 insertions(+), 45 deletions(-) diff --git a/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/installations/installations.md b/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/installations/installations.md index 6dc8d0828b..5b1673da8c 100644 --- a/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/installations/installations.md +++ b/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/installations/installations.md @@ -45,26 +45,25 @@ For a single AWS account, you'll deploy a CloudFormation stack that creates the

Step 2: Deploy CloudFormation Stack

- **Access the CloudFormation Template**: - - Go to [Port Data Sources](https://app.getport.io/settings/data-sources). - - Click **+ Add Integration** → **AWS Hosted by Port**. - - Select **Single Account** and click the **"Click here"** link in step 3. + - Go to [Data Sources](https://app.getport.io/settings/data-sources) page. + - Click on the `+ Data source` button in the top right corner of the page. + - Select **AWS Hosted by Port** from the cloud providers section. + - Select **Single Account** and click the `Click here` link in step 3. - This will open CloudFormation with pre-configured parameters. - **Deploy via AWS Console**: - In the CloudFormation console, review the pre-configured parameters. - Scroll down to the bottom of the page. - - Check the box **"I acknowledge that AWS CloudFormation might create IAM resources with custom names"**. - - Click **Create Stack**. + - Check the box that states **"I acknowledge that AWS CloudFormation might create IAM resources with custom names"**. + - Click `Create Stack`.

Step 3: Configure Integration in Port

-- **Navigate to Port**: - - Go to your Port environment. - - Navigate to **[Port Data Sources](https://app.getport.io/settings/data-sources)**. +- Navigate to the [Data Sources](https://app.getport.io/settings/data-sources) page of your portal. - **Add AWS Hosted by Port Integration**: - - Click `+ Add Integration`. + - Click on the `+ Data source` button in the top right corner of the page. - Select **AWS Hosted by Port** from the cloud providers section. - **Get the Role ARN**: @@ -120,8 +119,8 @@ You must run the multi-account installation from your AWS Organizations **manage ::: - **Access Management Account**: - - Log into your AWS Organizations management account - - Navigate to [AWS Organizations](https://console.aws.amazon.com/organizations/) service + - Log into your AWS Organizations management account. + - Navigate to [AWS Organizations](https://console.aws.amazon.com/organizations/) service. - **Find Your OU IDs**: - In AWS Organizations, open **organizational units** in the left sidebar. @@ -131,7 +130,6 @@ You must run the multi-account installation from your AWS Organizations **manage - You can also target specific account IDs if needed. :::tip Common OU Naming Patterns Examples - - `ou-prod-12345678` (Production) - `ou-staging-87654321` (Staging) - `ou-dev-11223344` (Development) @@ -141,50 +139,49 @@ You must run the multi-account installation from your AWS Organizations **manage

Step 2: Deploy Multi-Account CloudFormation Stack

- **Access the CloudFormation Template**: - - Go to [Port Data Sources](https://app.getport.io/settings/data-sources) - - Click **+ Add Integration** → **AWS Hosted by Port** - - Select **Multiple Accounts** and click the **"Click here"** link in step 3 - - This will open CloudFormation with pre-configured parameters + - Go to the [Data sources](https://app.getport.io/settings/data-sources) page of your portal. + - Click on the `+ Data source` button in the top right corner of the page. + - Select **AWS Hosted by Port** from the cloud providers section. + - Select **Multiple Accounts** and click the `Click here` link in step 3. + - This will open CloudFormation with pre-configured parameters. - **Deploy via AWS Console**: - - In the CloudFormation console, review the pre-configured parameters - - Scroll down to the bottom of the page - - Check the box **"I acknowledge that AWS CloudFormation might create IAM resources with custom names"** - - Click **Create Stack** + - In the CloudFormation console, review the pre-configured parameters. + - Scroll down to the bottom of the page. + - Check the box **"I acknowledge that AWS CloudFormation might create IAM resources with custom names"**. + - Click `Create Stack`.

Step 3: Monitor Deployment

- **Check StackSet Status**: - - Go to **CloudFormation** → **StackSets** in your management account - - Monitor the deployment progress across all target accounts - - Ensure all stack instances show "CREATE_COMPLETE" status + - Go to **CloudFormation** → **StackSets** in your management account. + - Monitor the deployment progress across all target accounts. + - Ensure all stack instances show `CREATE_COMPLETE` status. - **Verify IAM Roles**: - - Check that the IAM roles were created in each target account + - Check that the IAM roles were created in each target account.

Step 4: Configure Integration in Port

-- **Navigate to Port**: - - Go to your Port environment - - Navigate to **[Port Data Sources](https://app.getport.io/settings/data-sources)** +- Navigate to the [Data sources](https://app.getport.io/settings/data-sources) page of your portal. - **Add AWS Hosted by Port Integration**: - - Click **+ Add Integration** - - Select **AWS Hosted by Port** from the cloud providers section + - Click on the `+ Data source` button in the top right corner of the page. + - Select **AWS Hosted by Port** from the cloud providers section. - **Get the Role ARN**: - - After CloudFormation deployment completes, go to the **Outputs** tab - - Copy the **PortintegrationRoleArn** value + - After CloudFormation deployment completes, go to the **Outputs** tab. + - Copy the **PortintegrationRoleArn** value. - **Complete Integration Setup**: - - Return to the Port integration form - - Paste the **Management Account Role ARN** into the **Account Role Arn** field - - Click **Done** + - Return to the Port integration form. + - Paste the **Management Account Role ARN** into the **Account Role Arn** field. + - Click `Done`. - **Verify Multi-Account Connection**: - - Port will automatically detect the IAM roles across all accounts - - The integration will start discovering resources from all configured accounts + - Port will automatically detect the IAM roles across all accounts. + - The integration will start discovering resources from all configured accounts. @@ -195,14 +192,14 @@ You must run the multi-account installation from your AWS Organizations **manage After installation, verify that the integration is working: 1. **Check Integration Status**: - - Go to **Settings** → **Integrations** - - Verify the AWS Hosted by Port integration shows as "Active" - - Check for any error messages + - Go to **Settings** → **Integrations**. + - Verify the AWS Hosted by Port integration shows as "Active". + - Check for any error messages. 2. **Verify Data Flow**: - Go to **Software Catalog** - - Look for entities created by the integration - - Verify that AWS resources are being imported correctly + - Look for entities created by the integration. + - Verify that AWS resources are being imported correctly. ## Troubleshooting @@ -212,8 +209,8 @@ Common Installation Issue - CloudFormation Stack Creation Failures. **Error**: `Stack creation failed: CREATE_FAILED` **Solutions**: -- **Invalid Port Organization ID**: Verify the format is `org_` followed by alphanumeric characters -- **Duplicate Integration Identifier**: Use a unique identifier that hasn't been used before -- **Insufficient IAM Permissions**: Ensure your AWS user has CloudFormation and IAM permissions -- **OIDC Provider Already Exists**: Set "Create OIDC Provider" to `false` if you already have one +- **Invalid Port Organization ID**: Verify the format is `org_` followed by alphanumeric characters. +- **Duplicate Integration Identifier**: Use a unique identifier that hasn't been used before. +- **Insufficient IAM Permissions**: Ensure your AWS user has CloudFormation and IAM permissions. +- **OIDC Provider Already Exists**: Set "Create OIDC Provider" to `false` if you already have one. From 2eef34e3768b789be3a9ee79e392f85cfdfa0ed2 Mon Sep 17 00:00:00 2001 From: Sivan Elkabes Date: Wed, 10 Sep 2025 12:39:49 +0300 Subject: [PATCH 12/16] Change hierarchy of files and folders --- .../cloud-providers/aws-v3/{aws-v3.md => Overview.md} | 10 +++++----- .../{installations => }/iam-role-architecture.md | 2 +- .../aws-v3/{installations => }/installations.md | 8 ++++---- .../aws-v3/installations/_category_.json | 4 ---- 4 files changed, 10 insertions(+), 14 deletions(-) rename docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/{aws-v3.md => Overview.md} (95%) rename docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/{installations => }/iam-role-architecture.md (99%) rename docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/{installations => }/installations.md (96%) delete mode 100644 docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/installations/_category_.json diff --git a/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/aws-v3.md b/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/Overview.md similarity index 95% rename from docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/aws-v3.md rename to docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/Overview.md index 069ed54803..12e1294a6b 100644 --- a/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/aws-v3.md +++ b/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/Overview.md @@ -1,5 +1,5 @@ --- -sidebar_position: 3 +sidebar_position: 1 --- import Tabs from "@theme/Tabs"; @@ -7,7 +7,7 @@ import TabItem from "@theme/TabItem"; import Image from "@theme/IdealImage"; import MetricsAndSyncStatus from "/docs/build-your-software-catalog/sync-data-to-catalog/templates/_metrics_and_sync_status.mdx" -# AWS Hosted by Port +# Overview :::warning Beta Feature AWS Hosted by Port is currently in **beta mode** and is not yet available for all Port users. Contact your Port representative to request access to this integration. @@ -49,9 +49,9 @@ AWS Hosted by Port provides several advantages over the standard AWS integration ## Getting started -Continue to the [installation](./installations/installations.md) guide to learn how to install AWS Hosted by Port. +Continue to the [installation](./installations.md) guide to learn how to install AWS Hosted by Port. -For detailed information about the IAM role architecture and security model, see the [IAM Role Architecture](./installations/iam-role-architecture.md) guide. +For detailed information about the IAM role architecture and security model, see the [IAM Role Architecture](./iam-role-architecture.md) guide. ## Configuration @@ -64,7 +64,7 @@ The mapping makes use of the [JQ JSON processor](https://stedolan.github.io/jq/m This is the default mapping configuration you get after installing AWS Hosted by Port.
-Default mapping configuration (Click to expand) +Default mapping configuration (click to expand) ```yaml showLineNumbers resources: diff --git a/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/installations/iam-role-architecture.md b/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/iam-role-architecture.md similarity index 99% rename from docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/installations/iam-role-architecture.md rename to docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/iam-role-architecture.md index cd46f118f4..fb66e4ca70 100644 --- a/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/installations/iam-role-architecture.md +++ b/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/iam-role-architecture.md @@ -1,5 +1,5 @@ --- -sidebar_position: 2 +sidebar_position: 3 --- # IAM role architecture diff --git a/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/installations/installations.md b/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/installations.md similarity index 96% rename from docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/installations/installations.md rename to docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/installations.md index 5b1673da8c..bab28a3836 100644 --- a/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/installations/installations.md +++ b/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/installations.md @@ -1,5 +1,5 @@ --- -sidebar_position: 1 +sidebar_position: 2 --- import Tabs from "@theme/Tabs"; @@ -7,8 +7,8 @@ import TabItem from "@theme/TabItem"; # Installation -:::warning Beta Access Required -AWS Hosted by Port is currently in beta mode. Contact your Port representative to request access to this integration before proceeding with installation. +:::warning Beta Feature +AWS Hosted by Port is currently in **beta mode** and is not yet available for all Port users. Contact your Port representative to request access to this integration. ::: AWS Hosted by Port is available through **Port's Ocean SaaS platform**. @@ -197,7 +197,7 @@ After installation, verify that the integration is working: - Check for any error messages. 2. **Verify Data Flow**: - - Go to **Software Catalog** + - Go to the [catalog](https://app.getport.io/organization/catalog) page of your portal. - Look for entities created by the integration. - Verify that AWS resources are being imported correctly. diff --git a/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/installations/_category_.json b/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/installations/_category_.json deleted file mode 100644 index d5a722de8d..0000000000 --- a/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/installations/_category_.json +++ /dev/null @@ -1,4 +0,0 @@ -{ - "label": "Installations", - "position": 1 -} \ No newline at end of file From ae591e9e9de2e05a3618df908a2c188c330bc0bd Mon Sep 17 00:00:00 2001 From: Sivan Elkabes Date: Wed, 10 Sep 2025 17:34:50 +0300 Subject: [PATCH 13/16] Edited the installation while implementing it --- .../cloud-providers/aws-v3/Overview.md | 185 +++++++----------- .../aws-v3/iam-role-architecture.md | 17 +- .../cloud-providers/aws-v3/installations.md | 93 +++------ .../aws/AWS-CloudFormation-checkbox.png | Bin 0 -> 108988 bytes .../aws/PortIntegreationRoleArn-value.png | Bin 0 -> 86870 bytes 5 files changed, 101 insertions(+), 194 deletions(-) create mode 100644 static/img/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws/AWS-CloudFormation-checkbox.png create mode 100644 static/img/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws/PortIntegreationRoleArn-value.png diff --git a/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/Overview.md b/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/Overview.md index 12e1294a6b..ee6d742783 100644 --- a/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/Overview.md +++ b/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/Overview.md @@ -67,123 +67,76 @@ This is the default mapping configuration you get after installing AWS Hosted by Default mapping configuration (click to expand) ```yaml showLineNumbers +deleteDependentEntities: true +createMissingRelatedEntities: true +enableMergeEntity: true resources: -- kind: AWS::Organizations::Account - selector: - query: 'true' - port: - entity: - mappings: - identifier: .Id - title: .Name - blueprint: '"awsAccount"' - properties: - arn: .Arn - email: .Email - status: .Status - joined_method: .JoinedMethod - joined_timestamp: .JoinedTimestamp | sub(" "; "T") -- kind: AWS::S3::Bucket - selector: - query: 'true' - useGetResourceAPI: 'true' - port: - entity: - mappings: - identifier: .Identifier - title: .Identifier - blueprint: '"cloudResource"' - properties: - kind: .__Kind - region: .Properties.RegionalDomainName | capture(".*\\.(?[^\\.]+)\\.amazonaws\\.com") - | .region - tags: .Properties.Tags - arn: .Properties.Arn - link: .Properties | select(.Arn != null) | "https://console.aws.amazon.com/go/view?arn=" - + .Arn - relations: - account: .__AccountId -- kind: AWS::EC2::Instance - selector: - query: 'true' - port: - entity: - mappings: - identifier: .Identifier - title: .Identifier - blueprint: '"cloudResource"' - properties: - kind: .__Kind - region: .__Region - tags: .Properties.Tags - arn: .Properties.Arn - link: .Properties | select(.Arn != null) | "https://console.aws.amazon.com/go/view?arn=" - + .Arn - relations: - account: .__AccountId -- kind: AWS::ECS::Cluster - selector: - query: 'true' - useGetResourceAPI: 'true' - port: - entity: - mappings: - identifier: .Properties.Arn - title: .Identifier - blueprint: '"cloudResource"' - properties: - kind: .__Kind - region: .__Region - tags: .Properties.Tags - arn: .Properties.Arn - link: .Properties | select(.Arn != null) | "https://console.aws.amazon.com/go/view?arn=" - + .Arn - relations: - account: .__AccountId -- kind: AWS::Lambda::Function - selector: - query: 'true' - useGetResourceAPI: 'true' - port: - entity: - mappings: - identifier: .Properties.FunctionName - title: .Properties.FunctionName - blueprint: '"cloudResource"' - properties: - kind: .__Kind - region: .__Region - runtime: .Properties.Runtime - memory_size: .Properties.MemorySize - timeout: .Properties.Timeout - tags: .Properties.Tags - arn: .Properties.Arn - link: .Properties | select(.Arn != null) | "https://console.aws.amazon.com/go/view?arn=" - + .Arn - relations: - account: .__AccountId -- kind: AWS::RDS::DBInstance - selector: - query: 'true' - useGetResourceAPI: 'true' - port: - entity: - mappings: - identifier: .Properties.DBInstanceIdentifier - title: .Properties.DBInstanceIdentifier - blueprint: '"cloudResource"' - properties: - kind: .__Kind - region: .__Region - engine: .Properties.Engine - engine_version: .Properties.EngineVersion - instance_class: .Properties.DBInstanceClass - tags: .Properties.Tags - arn: .Properties.Arn - link: .Properties | select(.Arn != null) | "https://console.aws.amazon.com/go/view?arn=" - + .Arn - relations: - account: .__AccountId + - kind: AWS::Account::Info + selector: + query: 'true' + port: + entity: + mappings: + identifier: .Properties.Id + title: .Properties.Name + blueprint: '"awsAccount"' + - kind: AWS::S3::Bucket + selector: + query: 'true' + port: + entity: + mappings: + identifier: .Properties.Arn + title: .Properties.BucketName + blueprint: '"s3Bucket"' + properties: + arn: .Properties.Arn + region: .Properties.LocationConstraint + creationDate: .Properties.CreationDate + tags: .Properties.Tags + relations: + account: .__ExtraContext.AccountId + - kind: AWS::EC2::Instance + selector: + query: 'true' + port: + entity: + mappings: + identifier: .Properties.InstanceId + title: .Properties.InstanceId + blueprint: '"ec2Instance"' + properties: + instanceType: .Properties.InstanceType + state: .Properties.State.Name + publicIpAddress: .Properties.PublicIpAddress + privateIpAddress: .Properties.PrivateIpAddress + tags: .Properties.Tags + arn: >- + "arn:aws:ec2:" + .__Region + ":" + .__AccountId + ":instance/" + + .Properties.InstanceId + relations: + account: .__ExtraContext.AccountId + - kind: AWS::ECS::Cluster + selector: + query: 'true' + port: + entity: + mappings: + identifier: .Properties.ClusterArn + title: .Properties.ClusterName + blueprint: '"ecsCluster"' + properties: + status: .Properties.Status + runningTasksCount: .Properties.RunningTasksCount + activeServicesCount: .Properties.ActiveServicesCount + pendingTasksCount: .Properties.PendingTasksCount + registeredContainerInstancesCount: .Properties.RegisteredContainerInstancesCount + capacityProviders: .Properties.CapacityProviders + clusterArn: .Properties.ClusterArn + tags: .Properties.Tags + relations: + account: .__ExtraContext.AccountId + ```
diff --git a/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/iam-role-architecture.md b/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/iam-role-architecture.md index fb66e4ca70..b191fadd3e 100644 --- a/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/iam-role-architecture.md +++ b/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/iam-role-architecture.md @@ -15,6 +15,8 @@ The integration is designed to work with the full `ReadOnlyAccess` policy, which - **Reliable operation** without permission-related issues. ::: +If you prefer to create the IAM role manually rather than using the CloudFormation template, the following sections describe the setup we implement. This will help you understand the reasoning behind our design choices and adapt them if you decide to configure the role differently. + ## Role structure For multi-account setups, the role structure is replicated across all target accounts. @@ -74,7 +76,7 @@ The IAM role uses an **OIDC (OpenID Connect) trust policy** with **IRSA (IAM Rol The role uses the **AWS managed `ReadOnlyAccess` policy**, which provides comprehensive read-only access to all AWS services: -```yaml +```yaml showLineNumbers ManagedPolicyArns: - arn:aws:iam::aws:policy/ReadOnlyAccess ``` @@ -86,17 +88,6 @@ ManagedPolicyArns: - **AWS Maintained**: AWS manages and updates the policy as needed. - **Read-Only Security**: Only read permissions, no write/delete/create access. -## Permission categories - -Since the role uses the AWS managed `ReadOnlyAccess` policy, it has comprehensive read-only access to **all AWS services**. -Here are the key categories relevant to AWS Hosted by Port: - -- **Comprehensive Discovery**: Access to all AWS resource types. -- **Future-Proof**: New services are automatically supported without redeployment. -- **Operational Efficiency**: No CloudFormation updates needed when adding new services. -- **Consistent Access**: Same permission model across all services. -- **No Maintenance**: AWS manages policy updates. - ## Security considerations -From a security view point the integration uses a **read-only** role. It can list/describe and read metadata/tags, but cannot create, modify, delete, or change policies. No cross-account access is available unless it is explicitly configured. \ No newline at end of file +From a security view point the integration uses a **read-only** role. It can list/describe and read metadata/tags, but cannot create, modify, delete, or change any resource. \ No newline at end of file diff --git a/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/installations.md b/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/installations.md index bab28a3836..a454ef86ba 100644 --- a/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/installations.md +++ b/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/installations.md @@ -25,6 +25,12 @@ AWS Hosted by Port runs on **Port's servers** and connects to your AWS accounts 4. **Port exports the resources** to your Port account in the software catalog. 5. **Port periodically syncs** to keep your catalog up-to-date with your AWS infrastructure. +:::tip Why Can't I Use an Existing Role? +AWS Hosted by Port requires specific OIDC trust relationships and permissions that are automatically configured by the CloudFormation template. Using an existing role would require manual configuration of these complex trust relationships, which is why we provide the CloudFormation template to ensure proper setup. + +For detailed information about the IAM role architecture and permissions, see the [IAM Role Architecture](./iam-role-architecture.md) documentation. +::: + ## Installation methods -For a single AWS account, you'll deploy a CloudFormation stack that creates the necessary IAM roles. +For a single AWS account, you will deploy a CloudFormation stack that creates the necessary IAM roles.

Step 1: Access AWS Console

@@ -48,52 +54,40 @@ For a single AWS account, you'll deploy a CloudFormation stack that creates the - Go to [Data Sources](https://app.getport.io/settings/data-sources) page. - Click on the `+ Data source` button in the top right corner of the page. - Select **AWS Hosted by Port** from the cloud providers section. - - Select **Single Account** and click the `Click here` link in step 3. + - Select **Single Account** and click the `Click here` link in step 3 of the installation form. - This will open CloudFormation with pre-configured parameters. - **Deploy via AWS Console**: - In the CloudFormation console, review the pre-configured parameters. - Scroll down to the bottom of the page. - - Check the box that states **"I acknowledge that AWS CloudFormation might create IAM resources with custom names"**. + - Check the box that states **"I acknowledge that AWS CloudFormation might create IAM resources with custom names"**. + - Click `Create Stack`.

Step 3: Configure Integration in Port

-- Navigate to the [Data Sources](https://app.getport.io/settings/data-sources) page of your portal. - -- **Add AWS Hosted by Port Integration**: - - Click on the `+ Data source` button in the top right corner of the page. - - Select **AWS Hosted by Port** from the cloud providers section. - - **Get the Role ARN**: + - Ensure the stack shows `CREATE_COMPLETE` status. - After CloudFormation deployment completes, go to the **Outputs** tab. - - Copy the **Role ARN** value. - -- **Complete Integration Setup**: - - Return to the Port integration form. - - Paste the **Role ARN** into the **Account Role Arn** field. + - Copy the value of **PortIntegrationRoleArn**. + + - Paste it into the **Account Role Arn** field in the Port integration form. - Click `Done`. - **Verify Connection**: - Port will automatically detect the IAM role created by CloudFormation. - The integration will start discovering your AWS resources. -:::tip Why Can't I Use an Existing Role? -AWS Hosted by Port requires specific OIDC trust relationships and permissions that are automatically configured by the CloudFormation template. Using an existing role would require manual configuration of these complex trust relationships, which is why we provide the CloudFormation template to ensure proper setup. - -For detailed information about the IAM role architecture and permissions, see the [IAM Role Architecture](./iam-role-architecture.md) documentation. -::: - -For multiple AWS accounts, you'll use AWS Organizations and deploy the integration across multiple accounts using CloudFormation StackSets. +For multiple AWS accounts, you will use AWS Organizations and deploy the integration across multiple accounts using CloudFormation StackSets.

Understanding AWS Organizations

-- **Management Account**: The main account that manages your organization (also called "master account"). +- **Management Account**: The main account that manages your organization. - **Member Accounts**: Individual AWS accounts in your organization. - **Organizational Units (OUs)**: Logical groupings of accounts (like folders in a file system). - **OU IDs**: Unique identifiers for organizational units (format: `ou-abcd-12345678`). @@ -101,7 +95,7 @@ For multiple AWS accounts, you'll use AWS Organizations and deploy the integrati **Example Organization Structure**: ``` -Root (r-123456789) +Root (r-1234) ├── Management Account (123456789012) ├── Production OU (ou-prod-12345678) │ ├── Account: prod-app (234567890123) @@ -120,42 +114,36 @@ You must run the multi-account installation from your AWS Organizations **manage - **Access Management Account**: - Log into your AWS Organizations management account. - - Navigate to [AWS Organizations](https://console.aws.amazon.com/organizations/) service. + - Navigate to [AWS Organizations](https://us-east-1.console.aws.amazon.com/organizations/v2/home/accounts) service. - **Find Your OU IDs**: - In AWS Organizations, open **organizational units** in the left sidebar. - Click an OU (e.g., **Production**). - - Copy the OU ID from the details page (format `ou-xxxx-xxxxxxxx`). - - Repeat for each OU you want to include. + - Copy the OU ID from the details page (format `ou-xxxx-xxxxxxxx` or `r-xxxx`). - You can also target specific account IDs if needed. -:::tip Common OU Naming Patterns Examples -- `ou-prod-12345678` (Production) -- `ou-staging-87654321` (Staging) -- `ou-dev-11223344` (Development) -- `ou-shared-55667788` (Shared Services) -::: -

Step 2: Deploy Multi-Account CloudFormation Stack

- **Access the CloudFormation Template**: - Go to the [Data sources](https://app.getport.io/settings/data-sources) page of your portal. - Click on the `+ Data source` button in the top right corner of the page. - Select **AWS Hosted by Port** from the cloud providers section. - - Select **Multiple Accounts** and click the `Click here` link in step 3. - - This will open CloudFormation with pre-configured parameters. + - Select **Multiple Accounts** and paste the OU ID you previously copied. + - Choose the scope of the account (**All accounts**, **All accounts except selected**, **Selected accounts only**). + - Click the `Click here` link in step 3 of the installation form, this will open CloudFormation with pre-configured parameters. - **Deploy via AWS Console**: - In the CloudFormation console, review the pre-configured parameters. - Scroll down to the bottom of the page. - - Check the box **"I acknowledge that AWS CloudFormation might create IAM resources with custom names"**. + - Check the box **"I acknowledge that AWS CloudFormation might create IAM resources with custom names"**. + - Click `Create Stack`.

Step 3: Monitor Deployment

- **Check StackSet Status**: - - Go to **CloudFormation** → **StackSets** in your management account. + - Go to **CloudFormation** → **Stack** → **Stack details** → **Events tab** in your management account. - Monitor the deployment progress across all target accounts. - Ensure all stack instances show `CREATE_COMPLETE` status. @@ -164,19 +152,11 @@ You must run the multi-account installation from your AWS Organizations **manage

Step 4: Configure Integration in Port

-- Navigate to the [Data sources](https://app.getport.io/settings/data-sources) page of your portal. - -- **Add AWS Hosted by Port Integration**: - - Click on the `+ Data source` button in the top right corner of the page. - - Select **AWS Hosted by Port** from the cloud providers section. - - **Get the Role ARN**: - After CloudFormation deployment completes, go to the **Outputs** tab. - - Copy the **PortintegrationRoleArn** value. - -- **Complete Integration Setup**: - - Return to the Port integration form. - - Paste the **Management Account Role ARN** into the **Account Role Arn** field. + - Copy the value of **PortIntegrationRoleArn**. + + - Paste it into the **Account Role Arn** field in the Port integration form. - Click `Done`. - **Verify Multi-Account Connection**: @@ -187,21 +167,6 @@ You must run the multi-account installation from your AWS Organizations **manage
-## Verify installation - -After installation, verify that the integration is working: - -1. **Check Integration Status**: - - Go to **Settings** → **Integrations**. - - Verify the AWS Hosted by Port integration shows as "Active". - - Check for any error messages. - -2. **Verify Data Flow**: - - Go to the [catalog](https://app.getport.io/organization/catalog) page of your portal. - - Look for entities created by the integration. - - Verify that AWS resources are being imported correctly. - - ## Troubleshooting Common Installation Issue - CloudFormation Stack Creation Failures. @@ -209,8 +174,6 @@ Common Installation Issue - CloudFormation Stack Creation Failures. **Error**: `Stack creation failed: CREATE_FAILED` **Solutions**: -- **Invalid Port Organization ID**: Verify the format is `org_` followed by alphanumeric characters. -- **Duplicate Integration Identifier**: Use a unique identifier that hasn't been used before. - **Insufficient IAM Permissions**: Ensure your AWS user has CloudFormation and IAM permissions. - **OIDC Provider Already Exists**: Set "Create OIDC Provider" to `false` if you already have one. diff --git a/static/img/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws/AWS-CloudFormation-checkbox.png b/static/img/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws/AWS-CloudFormation-checkbox.png new file mode 100644 index 0000000000000000000000000000000000000000..07fd946a1d2618f579040af60aeb1fbd54ce9365 GIT binary patch literal 108988 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 KO6!vAKCj)?iwUXfJ49xtnuxZ;z(R#OB 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 by{T0wx2^X~>%P_>z|WP720BF-Aou?tHTpr; literal 0 HcmV?d00001 diff --git a/static/img/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws/PortIntegreationRoleArn-value.png b/static/img/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws/PortIntegreationRoleArn-value.png new file mode 100644 index 0000000000000000000000000000000000000000..7720c10e8556a254f1cc638022a1e9072131f7df GIT binary patch literal 86870 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

mF6P@LR{|W6wF?^_z0cbx>ukB9w%=-p9f`p$e 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 Date: Thu, 11 Sep 2025 14:54:01 +0300 Subject: [PATCH 14/16] add image for create_complete and change a couple more explanation lines --- .../cloud-providers/aws-v3/Overview.md | 8 +-- .../aws-v3/iam-role-architecture.md | 22 ++++--- .../cloud-providers/aws-v3/installations.md | 54 +++++++++--------- .../aws/CREATE_COMPLETE-status.png | Bin 0 -> 33457 bytes 4 files changed, 39 insertions(+), 45 deletions(-) create mode 100644 static/img/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws/CREATE_COMPLETE-status.png diff --git a/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/Overview.md b/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/Overview.md index ee6d742783..00f7e4d5fc 100644 --- a/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/Overview.md +++ b/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/Overview.md @@ -41,11 +41,9 @@ We're actively working on adding support for additional AWS resource types to pr AWS Hosted by Port provides several advantages over the standard AWS integration: -- **Fully Hosted**: No infrastructure to maintain, update, or monitor. -- **Simplified Installation**: Just deploy CloudFormation templates to create IAM roles. -- **Complete Data**: Ensures no missing or incomplete resource information. -- **Periodic Sync**: Regular updates to keep your catalog current. -- **Zero Maintenance**: Port handles all updates, scaling, and infrastructure management. +- **Fully hosted**: No infrastructure to maintain, update, or monitor. +- **Simplified installation**: Just deploy CloudFormation templates to create IAM roles. +- **Complete data**: Ensures no missing or incomplete resource information. ## Getting started diff --git a/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/iam-role-architecture.md b/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/iam-role-architecture.md index b191fadd3e..21a8c81b5e 100644 --- a/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/iam-role-architecture.md +++ b/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/iam-role-architecture.md @@ -37,7 +37,7 @@ PortIntegrationOIDCProvider: Value: !Ref IntegrationIdentifier ``` -**Key Details**: +**Key details**: - **EKS OIDC URL**: Points to Port's production EKS cluster in EU-West-1. - **Client ID**: Uses `sts.amazonaws.com` for IRSA authentication. - **Reusable**: Can be shared across multiple integrations in the same account. @@ -66,11 +66,9 @@ The IAM role uses an **OIDC (OpenID Connect) trust policy** with **IRSA (IAM Rol } ``` -**Key Security Features**: -- **IRSA Authentication**: Uses EKS service account-based authentication. -- **Audience Validation**: Only AWS STS service can assume the role. -- **Subject Validation**: Role is tied to Port's specific EKS service account. -- **Temporary Credentials**: All access uses short-lived tokens (typically 1 hour). +**Key security features**: +- **OIDC authentication**: Role is tied to Port's specific EKS service account. +- **Temporary credentials**: All access uses short-lived tokens (typically 1 hour). ### Permissions policy @@ -81,12 +79,12 @@ ManagedPolicyArns: - arn:aws:iam::aws:policy/ReadOnlyAccess ``` -**Strategic Benefits**: -- **Future-Proof**: Automatically includes new AWS services without CloudFormation updates. -- **Operational Simplicity**: No need to redeploy when adding support for new services. -- **Comprehensive Coverage**: Access to all AWS services with read-only permissions. -- **AWS Maintained**: AWS manages and updates the policy as needed. -- **Read-Only Security**: Only read permissions, no write/delete/create access. +**Strategic benefits**: +- **Future-proof**: Automatically includes new AWS services without CloudFormation updates. +- **Operational simplicity**: No need to redeploy when adding support for new services. +- **Comprehensive coverage**: Access to all AWS services with read-only permissions. +- **AWS maintained**: AWS manages and updates the policy as needed. +- **Read-Only security**: Only read permissions, no write/delete/create access. ## Security considerations diff --git a/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/installations.md b/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/installations.md index a454ef86ba..b5ac48c293 100644 --- a/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/installations.md +++ b/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/installations.md @@ -50,14 +50,15 @@ For a single AWS account, you will deploy a CloudFormation stack that creates th

Step 2: Deploy CloudFormation Stack

-- **Access the CloudFormation Template**: +- **Access the CloudFormation template**: - Go to [Data Sources](https://app.getport.io/settings/data-sources) page. - Click on the `+ Data source` button in the top right corner of the page. - Select **AWS Hosted by Port** from the cloud providers section. - - Select **Single Account** and click the `Click here` link in step 3 of the installation form. + - Select **Single Account**. + - In step 3 of the installation form, click the `Click here` link. This will open CloudFormation with pre-configured parameters. - This will open CloudFormation with pre-configured parameters. -- **Deploy via AWS Console**: +- **Deploy via AWS console**: - In the CloudFormation console, review the pre-configured parameters. - Scroll down to the bottom of the page. - Check the box that states **"I acknowledge that AWS CloudFormation might create IAM resources with custom names"**. @@ -67,15 +68,16 @@ For a single AWS account, you will deploy a CloudFormation stack that creates th

Step 3: Configure Integration in Port

-- **Get the Role ARN**: +- **Get the role ARN**: - Ensure the stack shows `CREATE_COMPLETE` status. + - After CloudFormation deployment completes, go to the **Outputs** tab. - Copy the value of **PortIntegrationRoleArn**. - Paste it into the **Account Role Arn** field in the Port integration form. - Click `Done`. -- **Verify Connection**: +- **Verify connection**: - Port will automatically detect the IAM role created by CloudFormation. - The integration will start discovering your AWS resources. @@ -87,13 +89,13 @@ For multiple AWS accounts, you will use AWS Organizations and deploy the integra

Understanding AWS Organizations

-- **Management Account**: The main account that manages your organization. -- **Member Accounts**: Individual AWS accounts in your organization. -- **Organizational Units (OUs)**: Logical groupings of accounts (like folders in a file system). +- **Management account**: The main account that manages your organization. +- **Member accounts**: Individual AWS accounts in your organization. +- **Organizational units (OUs)**: Logical groupings of accounts (like folders in a file system). - **OU IDs**: Unique identifiers for organizational units (format: `ou-abcd-12345678`). - **Root**: The top-level container for all accounts and OUs (format: `r-xxxxxxxxx`). -**Example Organization Structure**: +**Example organization structure**: ``` Root (r-1234) ├── Management Account (123456789012) @@ -112,27 +114,23 @@ Root (r-1234) You must run the multi-account installation from your AWS Organizations **management account**. This is because only the management account can deploy StackSets across member accounts. ::: -- **Access Management Account**: +- **Find your OU ID**: - Log into your AWS Organizations management account. - Navigate to [AWS Organizations](https://us-east-1.console.aws.amazon.com/organizations/v2/home/accounts) service. - -- **Find Your OU IDs**: - - In AWS Organizations, open **organizational units** in the left sidebar. - - Click an OU (e.g., **Production**). - - Copy the OU ID from the details page (format `ou-xxxx-xxxxxxxx` or `r-xxxx`). - - You can also target specific account IDs if needed. + - Under **Organizational structure** copy the OU ID from the details page (format `ou-xxxx-xxxxxxxx` or `r-xxxx`). + - You can also target specific account IDs if needed using the `Account scope` field.

Step 2: Deploy Multi-Account CloudFormation Stack

-- **Access the CloudFormation Template**: +- **Access the CloudFormation template**: - Go to the [Data sources](https://app.getport.io/settings/data-sources) page of your portal. - Click on the `+ Data source` button in the top right corner of the page. - Select **AWS Hosted by Port** from the cloud providers section. - Select **Multiple Accounts** and paste the OU ID you previously copied. - Choose the scope of the account (**All accounts**, **All accounts except selected**, **Selected accounts only**). - - Click the `Click here` link in step 3 of the installation form, this will open CloudFormation with pre-configured parameters. + - In step 3 of the installation form, click the `Click here` link, this will open CloudFormation with pre-configured parameters. -- **Deploy via AWS Console**: +- **Deploy via AWS console**: - In the CloudFormation console, review the pre-configured parameters. - Scroll down to the bottom of the page. - Check the box **"I acknowledge that AWS CloudFormation might create IAM resources with custom names"**. @@ -142,24 +140,24 @@ You must run the multi-account installation from your AWS Organizations **manage

Step 3: Monitor Deployment

-- **Check StackSet Status**: - - Go to **CloudFormation** → **Stack** → **Stack details** → **Events tab** in your management account. - - Monitor the deployment progress across all target accounts. - - Ensure all stack instances show `CREATE_COMPLETE` status. +- **Check StackSet status**: + - Go to **CloudFormation** → **Stacks** in your management account. + - Make sure your stack status is `CREATE_COMPLETE`. + -- **Verify IAM Roles**: +- **Verify IAM roles**: - Check that the IAM roles were created in each target account.

Step 4: Configure Integration in Port

-- **Get the Role ARN**: +- **Get the role ARN**: - After CloudFormation deployment completes, go to the **Outputs** tab. - Copy the value of **PortIntegrationRoleArn**. - Paste it into the **Account Role Arn** field in the Port integration form. - Click `Done`. -- **Verify Multi-Account Connection**: +- **Verify multi-Account connection**: - Port will automatically detect the IAM roles across all accounts. - The integration will start discovering resources from all configured accounts. @@ -174,6 +172,6 @@ Common Installation Issue - CloudFormation Stack Creation Failures. **Error**: `Stack creation failed: CREATE_FAILED` **Solutions**: -- **Insufficient IAM Permissions**: Ensure your AWS user has CloudFormation and IAM permissions. -- **OIDC Provider Already Exists**: Set "Create OIDC Provider" to `false` if you already have one. +- **Insufficient IAM permissions**: Ensure your AWS user has CloudFormation and IAM permissions. +- **OIDC provider already Eeists**: Set "Create OIDC Provider" to `false` if you already have one. diff --git a/static/img/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws/CREATE_COMPLETE-status.png b/static/img/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws/CREATE_COMPLETE-status.png new file mode 100644 index 0000000000000000000000000000000000000000..ad08b618d9db66146f1651bcf515585d7c83fcad GIT binary patch literal 33457 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 bctTFY+JTXY-^cvAzxBC-`qPrfrf>c~G*_A* literal 0 HcmV?d00001 From 1de01ba6715376f398dacbc378b698e46e61b5ad Mon Sep 17 00:00:00 2001 From: Sivan Elkabes Date: Sun, 14 Sep 2025 17:25:24 +0300 Subject: [PATCH 15/16] fix CR issue by Hadar --- .../cloud-providers/aws-v3/Overview.md | 6 +++--- .../cloud-providers/aws-v3/installations.md | 18 +++++++++--------- .../aws/installations/installation.md | 1 - ...heckbox.png => CloudFormationcheckbox.png} | Bin ...TE-status.png => CreateCompleteStatus.png} | Bin ...e.png => PortIntegreationRoleArnValue.png} | Bin 6 files changed, 12 insertions(+), 13 deletions(-) rename static/img/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws/{AWS-CloudFormation-checkbox.png => CloudFormationcheckbox.png} (100%) rename static/img/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws/{CREATE_COMPLETE-status.png => CreateCompleteStatus.png} (100%) rename static/img/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws/{PortIntegreationRoleArn-value.png => PortIntegreationRoleArnValue.png} (100%) diff --git a/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/Overview.md b/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/Overview.md index 00f7e4d5fc..22fdf14d0d 100644 --- a/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/Overview.md +++ b/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/Overview.md @@ -10,7 +10,7 @@ import MetricsAndSyncStatus from "/docs/build-your-software-catalog/sync-data-to # Overview :::warning Beta Feature -AWS Hosted by Port is currently in **beta mode** and is not yet available for all Port users. Contact your Port representative to request access to this integration. +AWS Hosted by Port is currently in **beta mode** and is not yet available for all Port users. Contact Port's support team to get access to this integration. ::: Port's AWS Hosted by Port integration allows you to import your AWS resources into Port with **zero maintenance required**. The integration is fully hosted and managed by Port, providing a seamless experience for discovering and managing your AWS infrastructure. @@ -37,9 +37,9 @@ The integration currently supports the following AWS resource types: We're actively working on adding support for additional AWS resource types to provide comprehensive coverage of your AWS infrastructure. ::: -## Key advantages over standard AWS integration +## Key advantages -AWS Hosted by Port provides several advantages over the standard AWS integration: +AWS Hosted by Port provides several advantages over the [self-hosted AWS integration](/aws/installations/installation): - **Fully hosted**: No infrastructure to maintain, update, or monitor. - **Simplified installation**: Just deploy CloudFormation templates to create IAM roles. diff --git a/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/installations.md b/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/installations.md index b5ac48c293..306d3b9cb1 100644 --- a/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/installations.md +++ b/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/installations.md @@ -8,10 +8,10 @@ import TabItem from "@theme/TabItem"; # Installation :::warning Beta Feature -AWS Hosted by Port is currently in **beta mode** and is not yet available for all Port users. Contact your Port representative to request access to this integration. +AWS Hosted by Port is currently in **beta mode** and is not yet available for all Port users. Contact Port's support team to get access to this integration. ::: -AWS Hosted by Port is available through **Port's Ocean SaaS platform**. +AWS Hosted by Port is available through [Port's Ocean SaaS framework](https://ocean.getport.io/integrations-library/). The installation process is simple - you only need to create IAM roles in your AWS accounts to grant the integration access to read your resources. The integration handles everything else automatically. @@ -19,7 +19,7 @@ The installation process is simple - you only need to create IAM roles in your A AWS Hosted by Port runs on **Port's servers** and connects to your AWS accounts using **OIDC (OpenID Connect)** authentication. Here's how it works: -1. **You create IAM roles** in your AWS accounts using our CloudFormation templates. +1. **You create IAM roles** in your AWS accounts using Port's CloudFormation templates. 2. **Port's servers assume these roles** using OIDC to get temporary AWS credentials. 3. **Port discovers your AWS resources** by calling AWS APIs with the assumed roles. 4. **Port exports the resources** to your Port account in the software catalog. @@ -62,7 +62,7 @@ For a single AWS account, you will deploy a CloudFormation stack that creates th - In the CloudFormation console, review the pre-configured parameters. - Scroll down to the bottom of the page. - Check the box that states **"I acknowledge that AWS CloudFormation might create IAM resources with custom names"**. - + - Click `Create Stack`. @@ -70,10 +70,10 @@ For a single AWS account, you will deploy a CloudFormation stack that creates th - **Get the role ARN**: - Ensure the stack shows `CREATE_COMPLETE` status. - + - After CloudFormation deployment completes, go to the **Outputs** tab. - Copy the value of **PortIntegrationRoleArn**. - + - Paste it into the **Account Role Arn** field in the Port integration form. - Click `Done`. @@ -134,7 +134,7 @@ You must run the multi-account installation from your AWS Organizations **manage - In the CloudFormation console, review the pre-configured parameters. - Scroll down to the bottom of the page. - Check the box **"I acknowledge that AWS CloudFormation might create IAM resources with custom names"**. - + - Click `Create Stack`. @@ -143,7 +143,7 @@ You must run the multi-account installation from your AWS Organizations **manage - **Check StackSet status**: - Go to **CloudFormation** → **Stacks** in your management account. - Make sure your stack status is `CREATE_COMPLETE`. - + - **Verify IAM roles**: - Check that the IAM roles were created in each target account. @@ -153,7 +153,7 @@ You must run the multi-account installation from your AWS Organizations **manage - **Get the role ARN**: - After CloudFormation deployment completes, go to the **Outputs** tab. - Copy the value of **PortIntegrationRoleArn**. - + - Paste it into the **Account Role Arn** field in the Port integration form. - Click `Done`. diff --git a/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws/installations/installation.md b/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws/installations/installation.md index 44ed1d8d7a..f556dcbd7b 100644 --- a/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws/installations/installation.md +++ b/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws/installations/installation.md @@ -23,7 +23,6 @@ Make sure you set up properly using our [Multiple Accounts guide](./multi_accoun ::: Choose one of the following installation methods: -Not sure which method is right for your use case? Check the available [installation methods](/build-your-software-catalog/sync-data-to-catalog/#installation-methods). diff --git a/static/img/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws/AWS-CloudFormation-checkbox.png b/static/img/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws/CloudFormationcheckbox.png similarity index 100% rename from static/img/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws/AWS-CloudFormation-checkbox.png rename to static/img/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws/CloudFormationcheckbox.png diff --git a/static/img/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws/CREATE_COMPLETE-status.png b/static/img/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws/CreateCompleteStatus.png similarity index 100% rename from static/img/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws/CREATE_COMPLETE-status.png rename to static/img/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws/CreateCompleteStatus.png diff --git a/static/img/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws/PortIntegreationRoleArn-value.png b/static/img/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws/PortIntegreationRoleArnValue.png similarity index 100% rename from static/img/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws/PortIntegreationRoleArn-value.png rename to static/img/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws/PortIntegreationRoleArnValue.png From 45a09f29415d163e3203d4a01911057200c55353 Mon Sep 17 00:00:00 2001 From: Sivan Elkabes Date: Sun, 14 Sep 2025 17:47:52 +0300 Subject: [PATCH 16/16] fixed broken link --- .../sync-data-to-catalog/cloud-providers/aws-v3/Overview.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/Overview.md b/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/Overview.md index 22fdf14d0d..9c8181e48a 100644 --- a/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/Overview.md +++ b/docs/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws-v3/Overview.md @@ -39,7 +39,7 @@ We're actively working on adding support for additional AWS resource types to pr ## Key advantages -AWS Hosted by Port provides several advantages over the [self-hosted AWS integration](/aws/installations/installation): +AWS Hosted by Port provides several advantages over the [self-hosted AWS integration](/build-your-software-catalog/sync-data-to-catalog/cloud-providers/aws/installations/installation.md): - **Fully hosted**: No infrastructure to maintain, update, or monitor. - **Simplified installation**: Just deploy CloudFormation templates to create IAM roles.