Takip et

AWS Hesaplar Arası Güvenli Operasyonlar: CustomResource’a Harici Kimlik Desteği

AWS bulutunda kaynak yönetimi yaparken hesaplar arası operasyonlar kaçınılmaz hale gelir. Ancak bu esneklik, beraberinde ciddi güvenlik riskleri de taşır. Bu makale, özellikle AwsCustomResource kullanırken çapraz hesap erişimini Harici Kimlik (External ID) ile nasıl güçlendirebileceğinizi adım adım açıklıyor.

Modern AWS altyapılarında, farklı iş yükleri, departmanlar veya ortamlar (geliştirme, test, üretim) için birden fazla AWS hesabı kullanmak oldukça yaygın bir yaklaşımdır. Bu çoklu hesap stratejisi, kaynak izolasyonu, maliyet yönetimi ve güvenlik kontrolü gibi pek çok avantaj sunar. Ancak, bu hesaplar arasında veri paylaşımı, otomasyon veya merkezi yönetim gibi ihtiyaçlar doğduğunda, çapraz hesap (cross-account) operasyonları devreye girer. Örneğin, merkezi bir güvenlik hesabı, tüm üretim hesaplarına belirli güvenlik politikalarını dağıtmak isteyebilir veya bir CI/CD boru hattı, farklı bir hesaptaki kaynakları yönetmek zorunda kalabilir.

Hesaplar arası erişim, genellikle IAM Rolleri aracılığıyla sağlanır. Bir hesap (güvenilen hesap), başka bir hesabın (güvenen hesap) belirli bir IAM Rolünü üstlenmesine (assume role) izin verir. Bu, kullanıcılara veya servislere doğrudan kimlik bilgisi paylaşmak zorunda kalmadan geçici yetkiler tanır. Ancak, bu kolaylık beraberinde kritik bir güvenlik riskini de getirir: “Confused Deputy” (Kafası Karışık Vekil) saldırısı.

Confused Deputy saldırısı, kötü niyetli bir üçüncü tarafın, aslında kendisi için tasarlanmamış bir hizmete, yetkilerini kötüye kullanarak erişmeye çalışması durumudur. Özellikle otomatikleştirilmiş sistemlerde veya üçüncü taraf entegrasyonlarında bu risk daha da artar. AWS, bu tür senaryoların önüne geçmek için Harici Kimlik (External ID) kavramını sunmuştur. Bu kimlik, rol üstlenme isteği sırasında beklendiği gibi bir “sır” olarak işlev görerek, güvenliğin temelini oluşturur. Bu bölümün ilerleyen kısımlarında, Confused Deputy saldırısını daha detaylı inceleyerek, neden Harici Kimlik kullanımının kritik bir güvenlik önlemi olduğunu daha iyi anlayacağız. Unutmamak gerekir ki, bir güvenlik ihlali durumunda, etkilenen hesapların sayısı ve etki alanı, çoklu hesap mimarisinde katlanarak artabilir. Bu nedenle, çapraz hesap etkileşimlerinde en katı güvenlik önlemlerini uygulamak hayati önem taşır.

Confused Deputy Saldırısı Nedir ve Bizi Nasıl Etkiler?

Confused Deputy saldırısı, yetkili bir hizmetin veya kaynağın, kötü niyetli bir aktör tarafından manipüle edilerek, aslında o aktörün erişmemesi gereken bir kaynağa erişmesini sağlaması durumudur. Senaryoyu daha iyi anlamak için somut bir örnek düşünelim: Diyelim ki A Hesabınız var ve B Hesabınızda kritik bir S3 kovası var. A Hesabındaki bir Lambda fonksiyonu (veya bizim konumuzda bir AwsCustomResource), B Hesabındaki S3 kovasına erişmek için B Hesabında tanımlı “MyCriticalBucketAccessRole” adında bir IAM Rolünü üstleniyor (assume role). Bu rolün Trust Policy’si, A Hesabındaki Lambda’nın (veya Custom Resource’un) bu rolü üstlenmesine izin veriyor.

Şimdi, eğer kötü niyetli bir kullanıcı veya uygulama, A Hesabındaki Lambda’yı kandırarak (örneğin, Lambda’ya gönderdiği bir tetikleyici ile), aslında erişmemesi gereken başka bir S3 kovasına (C Hesabında bulunan kötü niyetli bir kullanıcının kovası) veri aktarmasını sağlarsa, işte bu bir Confused Deputy saldırısıdır. Lambda, kendisine verilen talimatları yerine getirirken, farkında olmadan kötü niyetli bir aktöre hizmet etmiş olur. Burada Lambda, yetkili olmasına rağmen “kafası karışmış” ve yanlış bir amaç için kullanılmıştır.

Bu saldırı türü, özellikle iki farklı tarafın (örneğin, sizin AWS hesabınız ve bir üçüncü taraf SaaS uygulaması) IAM rolleri aracılığıyla etkileşim kurduğu senaryolarda büyük bir risk taşır. Eğer üçüncü taraf bir servis sizin hesabınızda bir rol üstlenebiliyorsa ve bu rolün Trust Policy’sinde bir kısıtlama yoksa, o servis, kendi kullanıcılarından gelen kötü niyetli bir istekle sizin hesabınızdaki kaynaklara istenmeyen eylemler yapabilir. Harici Kimlik (External ID), bu tür saldırıları önlemek için tasarlanmıştır. Trust Policy’ye bir External ID şartı ekleyerek, rol üstlenmek isteyen tarafın, sizin belirlediğiniz gizli bir değeri (External ID) sağlamasını zorunlu kılarsınız. Bu değer yalnızca sizin tarafınızdan ve rolü üstlenmesi beklenen güvenilir hizmet tarafından bilinir. Böylece, kötü niyetli bir aktör, yetkili hizmeti kandırsa bile, bu gizli External ID’yi bilmediği için rolü üstlenemez ve yetkisiz erişim sağlanamaz. Bu mekanizma, çapraz hesap operasyonlarında güvenliğin temel taşlarından biridir.

AWS IAM Rolleri ve Custom Resource Nedir?

AWS ekosisteminde güvenlik ve yetkilendirme, IAM (Identity and Access Management) servisinin temelini oluşturur. IAM Rolleri, geçici yetkilendirme sağlayarak, kullanıcılar, uygulamalar veya AWS servisleri arasında kimlik bilgilerini paylaşmadan güvenli erişim imkanı sunar. Bir IAM Rolü, belirli eylemleri gerçekleştirmesine izin verilen bir dizi izin politikasından oluşur. En önemli parçalarından biri ise “Trust Policy” (Güven Politikası)’dir. Bu politika, hangi varlıkların (örneğin, belirli bir AWS hesabı, bir EC2 örneği, bir Lambda fonksiyonu veya başka bir IAM Rolü) bu rolü üstlenmesine izin verildiğini tanımlar. Hesaplar arası operasyonlarda, bir hesapta tanımlanan rolün Trust Policy’si, başka bir hesabın bu rolü üstlenmesine izin verecek şekilde yapılandırılır. Bu, yetki devrini güvenli bir şekilde yönetmek için kritik bir bileşendir.

Gelelim “Custom Resource” kavramına. AWS CloudFormation veya AWS CDK (Cloud Development Kit) gibi altyapı kodu (Infrastructure as Code – IaC) araçları, AWS kaynaklarını deklaratif bir şekilde tanımlamanıza ve dağıtmanıza olanak tanır. Ancak, bazen CloudFormation’ın doğrudan desteklemediği belirli bir kaynağı oluşturmanız, güncellemeniz veya silmeniz gerekebilir. İşte tam bu noktada Custom Resource’lar devreye girer. Custom Resource, CloudFormation şablonunuza özel mantık eklemenizi sağlayan bir mekanizmadır. Arka planda genellikle bir AWS Lambda fonksiyonu çalıştırır. Bu Lambda fonksiyonu, CloudFormation’dan gelen olaylara (oluşturma, güncelleme, silme) yanıt verir ve ilgili AWS API çağrılarını yaparak özel kaynağınızı yönetir. Örneğin, CloudFormation’da olmayan bir üçüncü taraf API’yi çağırmak, bir veritabanında özel bir tablo oluşturmak veya karmaşık bir yapılandırma adımı gerçekleştirmek için Custom Resource kullanabilirsiniz.

AwsCustomResource (ACR), AWS CDK’nin sunduğu, özel bir Custom Resource türüdür. ACR, herhangi bir AWS API çağrısını yapmanızı sağlayan bir yardımcı araçtır. Normalde Custom Resource’lar için manuel olarak bir Lambda fonksiyonu yazmanız ve bu fonksiyonun CloudFormation olaylarını işlemesini sağlamanız gerekir. Ancak ACR, bu boilerplate kodu sizin için otomatik olarak oluşturur. Tek yapmanız gereken, ACR’ye hangi AWS API çağrısını yapacağını ve hangi parametreleri kullanacağını belirtmektir. Bu, IaC ile otomasyonu önemli ölçüde hızlandırır ve CloudFormation’ın doğal yeteneklerini genişletir. Örneğin, bir S3 kovasına bir object kopyalamak, bir SSM parametresini dinamik olarak ayarlamak veya başka bir hesaptaki bir kaynağın durumunu sorgulamak için ACR kullanabilirsiniz. Bu kolaylık, ACR’yi çapraz hesap operasyonlarında da popüler bir seçim haline getirir, ancak bu durumda güvenlik mekanizmalarını doğru bir şekilde uygulamak daha da önem kazanır.

AwsCustomResource ile Otomatikleştirme Neden Önemli?

AWS Cloud Development Kit (CDK), modern bulut altyapısı geliştirmenin merkezinde yer alan güçlü bir araçtır. Geliştiricilerin tanıdık programlama dilleri (Python, TypeScript, Java vb.) kullanarak AWS kaynaklarını kodla tanımlamasına olanak tanır. Bu “altyapı kodu” (Infrastructure as Code – IaC) yaklaşımı, manuel yapılandırma hatalarını azaltır, tekrarlanabilirliği artırır ve sürüm kontrolü ile işbirliğini kolaylaştırır. AWS CDK’nin sağladığı yüksek soyutlama seviyesi, karmaşık bulut mimarilerini daha yönetilebilir hale getirir. Ancak, AWS hizmetlerinin ve özelliklerinin çeşitliliği göz önüne alındığında, bazen CDK’nin veya CloudFormation’ın doğrudan desteklemediği özel senaryolar ortaya çıkabilir.

Uzman İpucu: AWS CDK ile altyapınızı kodlarken, mevcut tüm AWS API’lerini kullanabilme esnekliği, projelerinizde karşılaşabileceğiniz herhangi bir özel gereksinime hızlıca adapte olmanızı sağlar. AwsCustomResource bu esnekliği size sunar.

İşte bu noktada AwsCustomResource (ACR) devreye girerek CDK’nin otomasyon gücünü bir adım öteye taşır. ACR, temelinde bir Lambda fonksiyonu çalıştıran bir CloudFormation Custom Resource’udur. Bu sayede, CDK geliştiricileri, CloudFormation’ın doğrudan sunmadığı herhangi bir AWS API çağrısını, dağıtım süreçlerinin bir parçası olarak otomatik olarak gerçekleştirebilirler. Örneğin, bir EC2 instance’ına belirli bir kullanıcı verisi (user data) atamak, bir S3 kovasının varsayılan şifreleme ayarlarını detaylıca yapmak, bir üçüncü taraf API’yi entegre etmek veya hatta farklı bir AWS hesabındaki bir kaynağın durumunu sorgulamak gibi görevler ACR ile kolayca halledilebilir.

Otomatikleştirme, sadece kaynak oluşturma ve yapılandırma süreçlerini hızlandırmakla kalmaz, aynı zamanda insan hatasını minimize eder. Özellikle çoklu hesap ortamlarında, aynı yapılandırma veya eylemin birden fazla hesapta tutarlı bir şekilde uygulanması gerektiğinde ACR’nin önemi daha da artar. Örneğin, merkezi bir güvenlik hesabı, tüm alt hesaplarda belirli CloudWatch log grupları oluşturmak veya IAM rol politikalarını güncellemek için bir ACR kullanabilir. Bu, “tek doğruluk kaynağı” prensibini benimseyerek, manuel yapılandırmadan kaynaklanabilecek tutarsızlıkları ve güvenlik açıklarını ortadan kaldırır. ACR, altyapınızın sadece bir parçası olmakla kalmaz, aynı zamanda DevOps süreçlerinizin ve sürekli teslimat (CI/CD) boru hatlarınızın ayrılmaz bir parçası haline gelir, böylece hızlı, güvenilir ve güvenli dağıtımlar yapmanıza olanak tanır.

Harici Kimlik (External ID) Nedir ve Güvenliği Nasıl Sağlar?

Harici Kimlik (External ID), AWS IAM’in çapraz hesap erişim güvenliğini artıran kritik bir özelliğidir. En basit ifadeyle, bir IAM Rolünü üstlenmek (assume role) için bir gereklilik olarak tanımlanan rastgele bir dize değeridir. Bu değer, rol üstlenme isteği yapan tarafın, rolün tanımlandığı hesap tarafından beklendiğini kanıtlayan bir “sır” veya “parola” görevi görür.

Peki, Harici Kimlik tam olarak nasıl çalışır ve güvenliği nasıl sağlar? Temel mekanizma, rolün Trust Policy’sinde yatar. Bir IAM rolü oluşturduğunuzda veya güncellediğinizde, bu rolü kimlerin üstlenebileceğini belirten bir Trust Policy tanımlarsınız. Normalde bu politika, belirli bir AWS hesabının veya bir IAM kullanıcısının/rolünün bu rolü üstlenmesine izin verir. Ancak, bu tek başına Confused Deputy saldırılarına karşı tam koruma sağlamaz. Harici Kimlik eklediğinizde, Trust Policy’ye “Condition” (şart) bloğunda sts:ExternalId koşulu eklenir. Bu koşul, rolü üstlenme isteği yapanın, rolün Trust Policy’sinde belirtilen External ID değeri ile eşleşen bir External ID sağlamasını zorunlu kılar.

İşleyişi şöyle açıklayabiliriz: Diyelim ki sizin AWS hesabınız (Hesap A), başka bir AWS hesabındaki (Hesap B) bir IAM rolünü üstlenerek belirli işlemleri yapacak. Hesap B’deki rolün Trust Policy’si, Hesap A’nın bu rolü üstlenmesine izin verirken, aynı zamanda belirli bir External ID’nin de sağlanmasını şart koşuyor. Hesap A’dan rol üstlenme isteği geldiğinde, AWS STS (Security Token Service), isteği yapanın sağladığı External ID’yi, Hesap B’deki rolün Trust Policy’sindeki External ID ile karşılaştırır. Eğer bu iki değer eşleşirse, rol üstlenme işlemi başarılı olur ve Hesap A geçici kimlik bilgilerini alır. Eşleşmezse, istek reddedilir.

Bu mekanizma, Confused Deputy saldırısını nasıl önler? Kötü niyetli bir üçüncü taraf, Hesap A’daki yetkili bir servisi (örneğin, bir AwsCustomResource) manipüle ederek, Hesap B’deki rolü üstlenmesini sağlamaya çalışsa bile, bu üçüncü tarafın Trust Policy’de belirtilen gizli External ID’yi bilmesi mümkün değildir. Dolayısıyla, rol üstlenme isteği reddedilir ve kötü niyetli erişim engellenir. Harici Kimlik, rol üstlenme isteği yapanın sadece “kim” olduğunu (kimlik doğrulama), aynı zamanda “bu rolü üstlenmesinin beklendiğini” (niyet doğrulama) de kanıtlamasını sağlayarak, ekstra bir güvenlik katmanı ekler. Bu, özellikle üçüncü taraf servislerin sizin hesabınızdaki rolleri üstlendiği veya kendi iç çoklu hesap ortamlarınızda hassas işlemler için otomasyon kullandığınız senaryolarda hayati öneme sahiptir. Harici Kimlikler genellikle uzun, rastgele ve tahmin edilemez dizeler olmalıdır ve düzenli olarak değiştirilmeleri (rotasyon) güvenlik best practice’lerinden biridir. Bu sayede, sızma veya brute-force saldırılarına karşı direnç daha da artırılmış olur.

AwsCustomResource ile Harici Kimlik Kullanımını Nasıl Entegre Ederiz?

AwsCustomResource (ACR), AWS CDK ile CloudFormation’ın yeteneklerini genişletmek için harika bir araç olsa da, çapraz hesap operasyonlarında güvenliği sağlamak için Harici Kimlik (External ID) entegrasyonu kritik bir adımdır. ACR, temelinde bir Lambda fonksiyonu çalıştırdığı için, bu Lambda’nın başka bir hesaptaki bir rolü üstlenmesi gerektiğinde, bu rolün Trust Policy’sine External ID şartını eklemeli ve ACR’nin bu External ID’yi sağlayacak şekilde yapılandırılmasını sağlamalıyız. İşte adım adım bu entegrasyonu nasıl gerçekleştireceğiniz:

Öncelikle, senaryomuzu netleştirelim: Bir Kaynak Hesap (Source Account) içindeki bir AwsCustomResource, bir Hedef Hesap (Target Account) içindeki bir IAM rolünü üstlenecek ve bu rol aracılığıyla Hedef Hesapta belirli bir AWS API çağrısı yapacak. Hedef Hesap’taki rol, güvenlik amacıyla bir External ID gerektirecek.

Hedef Hesapta Rol Tanımlaması: Trust Policy’ye External ID Ekleme

İlk adım, Hedef Hesap’ta AwsCustomResource’un üstleneceği IAM rolünü oluşturmak veya mevcut bir rolü güncellemektir. Bu rolün Trust Policy’si, Kaynak Hesap’taki AWS hesabının rolü üstlenmesine izin vermeli ve bir sts:ExternalId koşulu içermelidir. İşte bir AWS CDK örneği:


import * as iam from 'aws-cdk-lib/aws-iam';
import { Stack, StackProps } from 'aws-cdk-lib';
import { Construct } from 'constructs';

export class TargetAccountStack extends Stack {
  constructor(scope: Construct, id: string, props?: StackProps) {
    super(scope, id, props);

    // Bu, Kaynak Hesap'ın AWS Hesap Kimliği olmalı
    const sourceAccountArn = arn:aws:iam::${props?.env?.account}:root; 
    const externalId = 'MySecureAndUniqueExternalId123'; // Güvenli, rastgele bir External ID

    // AwsCustomResource'un üstleneceği IAM Rolü
    const crossAccountRole = new iam.Role(this, 'CrossAccountAccessRole', {
      assumedBy: new iam.FederatedPrincipal(
        'arn:aws:iam::aws:policy/service-role/AWSLambdaBasicExecutionRole', // Bu, temsili, asıl ARN aşağıdaki gibi olmalı
        {
          StringEquals: {
            'sts:ExternalId': externalId,
          },
          'aws:SourceAccount': props?.env?.account, // Sadece belirli bir hesaptan geliyorsa
        },
        'sts:AssumeRole'
      ),
      // Gerçekte, assumedBy şuna benzer olmalı:
      // assumedBy: new iam.AccountPrincipal(sourceAccountAccountID).withConditions({
      //   StringEquals: {
      //     'sts:ExternalId': externalId,
      //   },
      // }),
      // veya daha geneli:
      assumedBy: new iam.AnyPrincipal().withConditions({
        StringEquals: {
          'sts:ExternalId': externalId,
        },
        // Daha güvenli hale getirmek için isteği yapan arn'i de kısıtlayabiliriz
        'aws:PrincipalArn': sourceAccountArn, 
      }),
      description: 'Role for cross-account access from AwsCustomResource with External ID',
    });

    // Bu role, Hedef Hesapta yapması gereken izinleri ekleyin
    // Örneğin, S3 kovasına erişim izni
    crossAccountRole.addToPolicy(new iam.PolicyStatement({
      actions: ['s3:GetObject', 's3:PutObject'],
      resources: ['arn:aws:s3:::my-target-bucket/*', 'arn:aws:s3:::my-target-bucket'],
    }));

    // CDK çıktısı olarak rol ARN'ini kullanışlı hale getirebiliriz
    // new CfnOutput(this, 'CrossAccountRoleArn', {
    //   value: crossAccountRole.roleArn,
    // });
  }
}

Yukarıdaki kod bloğunda:

  • sourceAccountArn: Kaynak hesabın ARN'i, bu sayede sadece bu hesabın rolü üstlenmesine izin verilir.
  • externalId: Belirlediğimiz Harici Kimlik. Bu değer hem Hedef Hesap'taki rolün Trust Policy'sinde hem de Kaynak Hesap'taki AwsCustomResource'da aynı olmalıdır.
  • assumedBy: Bu kısım, rolü üstlenmeye yetkili prensibi tanımlar. AnyPrincipal kullanarak herhangi bir prensibin (ancak sadece belirtilen External ID ve SourceAccount ile) rolü üstlenmesine izin veriyoruz. Daha spesifik olarak new iam.AccountPrincipal(sourceAccountAccountID) de kullanabilirsiniz.
  • StringEquals koşulu: sts:ExternalId anahtarını kullanarak, rolü üstlenmek isteyenin bizim belirlediğimiz externalId değerini sağlamasını zorunlu kılıyoruz.
  • aws:PrincipalArn koşulu: Ek bir güvenlik katmanı olarak, isteği yapanın belirli bir ARN'e sahip olmasını da şart koşabiliriz.

Kaynak Hesapta AwsCustomResource Konfigürasyonu: External ID'yi Dinamik Olarak Kullanma

Şimdi sıra Kaynak Hesap'a geldi. Burada, AwsCustomResource'u oluşturacağız ve Hedef Hesap'taki rolü üstlenirken gerekli External ID'yi sağlayacak şekilde yapılandıracağız. AwsCustomResource, çağrıları yaparken sts.assumeRole API'sini kullanmalı ve bu çağrıya ExternalId parametresini dahil etmelidir.


import * as cdk from 'aws-cdk-lib';
import * as custom_resources from 'aws-cdk-lib/custom-resources';
import * as iam from 'aws-cdk-lib/aws-iam';
import { Construct } from 'constructs';

export class SourceAccountStack extends cdk.Stack {
  constructor(scope: Construct, id: string, props?: cdk.StackProps) {
    super(scope, id, props);

    const targetAccountRoleArn = 'arn:aws:iam::123456789012:role/CrossAccountAccessRole'; // Hedef Hesap'taki rolün ARN'i
    const externalId = 'MySecureAndUniqueExternalId123'; // Hedef Hesap'taki ile aynı External ID

    // AwsCustomResource'un çalışacağı Lambda'nın üstleneceği rol
    const customResourceLambdaRole = new iam.Role(this, 'CustomResourceLambdaRole', {
      assumedBy: new iam.ServicePrincipal('lambda.amazonaws.com'),
      description: 'Role for AwsCustomResource Lambda to assume cross-account role',
    });

    // CustomResourceLambdaRole'a, Hedef Hesap'taki rolü üstlenme izni verilmeli
    customResourceLambdaRole.addToPolicy(new iam.PolicyStatement({
      actions: ['sts:AssumeRole'],
      resources: [targetAccountRoleArn],
    }));
    
    // AWS Custom Resource'u tanımla
    new custom_resources.AwsCustomResource(this, 'MyCrossAccountCustomResource', {
      onCreate: {
        service: 'STS',
        action: 'assumeRole',
        parameters: {
          RoleArn: targetAccountRoleArn,
          RoleSessionName: 'CustomResourceSession',
          ExternalId: externalId, // BURASI KRİTİK: External ID'yi burada sağlıyoruz
        },
        // Bu çağrının sonucunu CloudFormation'a döndürme
        physicalResourceId: custom_resources.PhysicalResourceId.of('MyCrossAccountResourceID'),
      },
      // Opsiyonel: Diğer API çağrılarını hedef hesaptaki yeni rol ile yapma
      onUpdate: {
        service: 'S3',
        action: 'putObject', // Örnek bir S3 işlemi
        parameters: {
          Bucket: 'my-target-bucket', // Hedef hesaptaki kova
          Key: 'custom-resource-output.txt',
          Body: 'Hello from custom resource!',
        },
        // Çağrıyı yapacak rolü belirtiyoruz: targetAccountRoleArn
        // Bu, assumeRole çağrısından dönen geçici kimlik bilgilerini kullanacaktır
        // Ancak doğrudan AwsCustomResource'da bu karmaşık. Genellikle bu tip işlemleri
        // ayrı bir Lambda'da yapmak ve o Lambda'nın assumeRole yapması daha yaygındır.
        // AwsCustomResource doğrudan assumeRole yapıp ardından farklı bir API çağıramaz
        // aynı custom resource tanımı içinde.
        // Bu yüzden, onUpdate veya onCreate içinde assumeRole yapıyorsanız,
        // diğer tüm işlemler ayrı bir Lambda fonksiyonu içinde yapılmalı ve
        // assumeRole'dan dönen kimlik bilgileri o Lambda'ya aktarılmalıdır.
        // Ancak bu örnekte basitleştirme amacıyla assumeRole'un kendisi bir işlem olarak gösterildi.
        // Daha gerçekçi senaryo için aşağıya bakın.
      },
      // Eğer CustomResource'un Lambda'sı başka bir rol üstlenecekse,
      // o rolün yetkilerini burada tanımlamalısınız.
      policy: custom_resources.AwsCustomResourcePolicy.fromSdkCalls({
        resources: custom_resources.AwsCustomResourcePolicy.ANY_RESOURCE, // İlgili kaynakları daha spesifik yapın
      }),
      // CustomResource'un çalışacağı Lambda fonksiyonunun rolünü belirtiyoruz
      role: customResourceLambdaRole,
    });

    // Gerçekçi bir cross-account operasyon senaryosu:
    // AwsCustomResource, Hedef Hesap'taki bir SSM parametresini güncellemek için kullanılıyor.
    // Bu işlem için Hedef Hesap'taki rolü üstlenmesi gerekiyor.
    new custom_resources.AwsCustomResource(this, 'UpdateTargetAccountSsmParameter', {
        onCreate: {
            service: 'SSM',
            action: 'putParameter',
            parameters: {
                Name: '/my-app/config/value',
                Value: 'Updated from Source Account',
                Type: 'String',
                Overwrite: true,
            },
            physicalResourceId: custom_resources.PhysicalResourceId.of('SsmParameterUpdate'),
            // İŞTE BURADA, bu API çağrısını yaparken üstleneceği rolü belirtiyoruz.
            // Bu rol, yukarıda Hedef Hesap'ta tanımladığımız ve External ID gerektiren rol olmalı.
            // AwsCustomResource'un SDK çağrılarında assumeRole ile bir rol üstlenip
            // o rol ile işlem yapması için, output parametresini kullanıp
            // assumeRole'dan dönen kimlik bilgilerini almak ve
            // sonraki çağrıda bu kimlik bilgilerini kullanmak gerekir.
            // Ancak AwsCustomResource, tek bir çağrı içinde bunu doğrudan desteklemez.
            // En doğru yöntem, customResourceLambdaRole'un hedef rolü üstlenmesine izin verip,
            // AwsCustomResource içinde bir lambda fonksiyonu çağırıp, bu lambda fonksiyonunun
            // sts.assumeRole yapıp ardından hedef API çağrısını yapmasıdır.
            // Kod örneğini basitleştirmek adına, AwsCustomResource'un execution rolüne
            // hedef rolü üstlenme yetkisi verip, AwsCustomResource'un doğrudan
            // Hedef Hesap'ta bir işlem yaptığını varsayıyoruz. Bu, CloudFormation'ın
            // arka planda gerekli yetkilendirme akışını yönettiği anlamına gelir.
            // Ancak, bu yaklaşım, hedef hesaptaki kaynaklara erişmek için
            // AwsCustomResource'un execution rolüne (customResourceLambdaRole)
            // direkt olarak yetki vermek anlamına gelir ki bu, External ID'nin amacına aykırıdır.
            // DOĞRU YÖNTEM, AwsCustomResource'un bir Lambda'yı tetiklemesi ve bu Lambda'nın
            // sts.AssumeRole ile hedef rolü üstlenerek (External ID sağlayarak) işlemi yapmasıdır.
            // Bu örneği basitleştirmek adına, AwsCustomResource'un kendi Execution Rolü'nün
            // Hedef Hesap'taki rolü üstlenip S3 işlemine yetkilendirildiğini varsayalım.
            // Bu durumda, "TargetAccountRoleArn" değerini policy kısmında kullanacağız.
        },
        // Bu custom resource'un kendi yürütme rolü (customResourceLambdaRole)
        // Hedef Hesap'taki targetAccountRoleArn rolünü üstlenmeye yetkili olmalı.
        policy: custom_resources.AwsCustomResourcePolicy.fromStatements([
          new iam.PolicyStatement({
            actions: ['sts:AssumeRole'],
            resources: [targetAccountRoleArn],
          }),
          new iam.PolicyStatement({
            actions: ['ssm:PutParameter'],
            resources: [arn:aws:ssm:${this.region}:${cdk.Stack.of(this).account}:parameter/my-app/config/value],
            // Gerçekte bu kaynak, Hedef Hesap'ta olmalı
            // resources: [arn:aws:ssm:${this.region}:${targetAccountId}:parameter/my-app/config/value],
          }),
        ]),
        role: customResourceLambdaRole,
    });
  }
}

Yukarıdaki kodda, AwsCustomResource'un onCreate (veya onUpdate, onDelete) bloğunda direkt olarak bir STS assumeRole çağrısı gösterildi. Bu çağrıya ExternalId parametresi eklenerek, Hedef Hesap'taki rolün beklentisi karşılanıyor.

Önemli Not: AwsCustomResource'un tek bir çağrı içinde assumeRole yapıp ardından o rol ile başka bir API çağrısı yapması doğrudan kolay değildir. Genellikle, assumeRole çağrısı ayrı bir Lambda fonksiyonu içinde yapılır, dönen geçici kimlik bilgileri alınır ve bu kimlik bilgileri kullanılarak Hedef Hesap'taki diğer API çağrıları gerçekleştirilir. Ya da AwsCustomResource'un yürütme rolüne (customResourceLambdaRole), Hedef Hesap'taki rolü üstlenme izni verilir ve AwsCustomResource, Hedef Hesap'taki bir işlemi doğrudan çağırmaya çalışır. Bu durumda, CloudFormation'ın arka planda rol üstlenme sürecini yönettiği varsayılır, ancak bu doğrudan External ID'yi SDK çağrısı olarak geçirme örneği değildir. Yukarıdaki örneğimizde policy kısmında sts:AssumeRole iznini vermemiz ve onCreate içinde service: 'SSM', action: 'putParameter' gibi bir işlem yaparken, AwsCustomResource'un bu rolü üstlenip o yetkilerle işlemi yapmasını sağlamamız gerekir. Bu durumda ExternalId, AWS SDK çağrısı içinde değil, rol üstlenirken arka planda CloudFormation tarafından sağlanmalıdır. Bu karmaşıklık nedeniyle, çoğu durumda External ID kullanımı, ya bir doğrudan sts.assumeRole çağrısı yapan özel bir Lambda içinde ya da üçüncü taraf bir hizmetin sizin hesabınızdaki bir rolü üstlenmesi senaryosunda daha belirgindir.

Eğer AwsCustomResource'un Lambda fonksiyonunun doğrudan Hedef Hesap'taki rolü üstlenmesini ve ardından bu rol ile bir API çağrısı yapmasını istiyorsanız, Lambda'nın çalışma zamanı kodunda sts.assumeRole çağrısını yapmanız ve dönen kimlik bilgilerini kullanarak yeni bir AWS SDK istemcisi oluşturmanız gerekir. Bu da AwsCustomResource'un sağladığı kolaylığın dışına çıkarak, daha geleneksel bir Custom Resource Lambda'sı yazmayı gerektirir.

Bu makale, AwsCustomResource'un arkasındaki mekanizmanın, yani Lambda'nın, bir rolü üstlenirken External ID'yi nasıl kullanabileceğini ve hedef rolün nasıl yapılandırılması gerektiğini gösteriyor. Eğer AwsCustomResource'un kendisi direkt olarak sts:AssumeRole yapıyorsa (örnekteki gibi), ExternalId parametresini direkt olarak parameters içinde belirterek bunu sağlayabilirsiniz.

Gerçek Dünya Senaryoları: Harici Kimlik ile Güvenli Cross-Account İşlemleri

Harici Kimlik (External ID) ve AwsCustomResource ikilisi, AWS çoklu hesap ortamlarında birçok gerçek dünya güvenlik ve otomasyon senaryosunu mümkün kılar. İşte bu kombinasyonun gücünü gösteren iki vaka analizi:

Vaka Analizi 1: Merkezi Güvenlik Yönetimi için Güvenli Politika Dağıtımı

Büyük bir kuruluşun birden fazla AWS hesabı kullandığını düşünelim. Bu hesaplar, geliştirme, test, üretim ve farklı iş birimlerine ait olabilir. Güvenlik ekibi, tüm bu hesaplarda belirli güvenlik politikalarının (örneğin, şifreleme ayarları, ağ yapılandırmaları, denetim kuralları) tutarlı bir şekilde uygulanmasını istiyor. Ancak, güvenlik politikalarını her hesaba manuel olarak uygulamak zaman alıcı, hata eğilimli ve ölçeklenemez bir yöntemdir.

Senaryo: Merkezi Güvenlik Hesabı (Source Account), diğer tüm Üretim Hesaplarına (Target Accounts) belirli bir IAM politikası ekleyecek veya CloudWatch log grubu yapılandırmalarını güncelleyecek. Güvenlik ekibi, bu operasyonun yüksek güvenlik standartlarında yapılmasını ve "Confused Deputy" saldırılarına karşı korunmasını istiyor.

Çözüm:

  1. Hedef Hesaplarda Rol Tanımlaması: Her bir Üretim Hesabında, Merkezi Güvenlik Hesabı'nın üstlenebileceği bir IAM Rolü (örneğin, SecurityPolicyDeployerRole) tanımlanır. Bu rolün Trust Policy'si, Merkezi Güvenlik Hesabı'nın AWS Hesap Kimliğini (AccountPrincipal) ve benzersiz, rastgele bir ExternalId şartını içerir. Bu rol, gerekli IAM (örneğin, iam:AttachRolePolicy) veya CloudWatch (örneğin, logs:CreateLogGroup, logs:PutRetentionPolicy) izinlerine sahiptir.
  2. Merkezi Güvenlik Hesabında AwsCustomResource: Merkezi Güvenlik Hesabı'nda bir AWS CDK uygulaması geliştirilir. Bu uygulama, her bir Üretim Hesabı için ayrı bir AwsCustomResource oluşturur. Her AwsCustomResource'un Lambda fonksiyonu, Hedef Hesap'taki SecurityPolicyDeployerRole rolünü üstlenirken, o hesaba özel olarak belirlenmiş ExternalId'yi sağlar.
  3. Otomasyon ve Güvenlik: AwsCustomResource'lar, sts:AssumeRole çağrısını yaparak geçici kimlik bilgileri alır ve ardından bu kimlik bilgileriyle Hedef Hesap'taki istenen API çağrılarını (politika ekleme, log grubu güncelleme vb.) gerçekleştirir. External ID sayesinde, kötü niyetli bir aktör, Merkezi Güvenlik Hesabı'ndaki Custom Resource'u manipüle etmeye çalışsa bile, her hesaba özel External ID'yi bilmediği için rolü üstlenemez ve yetkisiz operasyonlar engellenir. Bu, güvenlik politikalarının merkezi ve güvenli bir şekilde dağıtılmasını sağlar, tutarlılığı garanti eder ve operasyonel yükü azaltır.

Vaka Analizi 2: Üçüncü Taraf Entegrasyonlarında Minimum Yetkilendirme

Bir SaaS şirketinin (örneğin, bir güvenlik izleme aracı veya bir yedekleme hizmeti) sizin AWS hesabınızda kaynaklar oluşturması veya mevcut kaynakları yönetmesi gerektiğini düşünün. Bu tür üçüncü taraf entegrasyonları, genellikle sizin AWS hesabınızda bir IAM rolünü üstlenerek çalışır.

Senaryo: Bir üçüncü taraf SaaS uygulaması (Örn: "ThirdPartySaaS" isimli bir platform), sizin AWS hesabınızdaki (Target Account) bir S3 kovasını yedekleyecek veya CloudWatch metriklerini toplayacak. SaaS platformu, sizin hesabınızda bir IAM rolü üstlenecek ve bu rolün sadece belirli S3 kovasına erişim izni olmasını istiyorsunuz. En önemlisi, SaaS'ın bu rolü üstlenirken, sadece kendi iç sistemlerinin tetiklediği yasal işlemler için kullanıldığından emin olmak istiyorsunuz.

Çözüm:

  1. Hesabınızda Rol Tanımlaması: Kendi AWS hesabınızda (Target Account) bir IAM Rolü (örneğin, ThirdPartySaaSBackupRole) oluşturursunuz. Bu rolün Trust Policy'si, ThirdPartySaaS'ın AWS Hesap Kimliğini (AccountPrincipal) ve SaaS platformunun size sağladığı benzersiz bir ExternalId'yi içerir. Bu External ID, yalnızca SaaS platformu tarafından bilinen ve size özel bir değerdir. Role, yalnızca belirli S3 kovalarına (s3:GetObject, s3:ListBucket) veya CloudWatch metriklerine (cloudwatch:GetMetricData) erişim gibi minimum gerekli izinler verilir.
  2. SaaS Entegrasyonu: SaaS platformunun arayüzünde, size sağladıkları External ID'yi ve oluşturduğunuz ThirdPartySaaSBackupRole'ün ARN'sini belirtirsiniz. SaaS platformu, sizin hesabınızdaki rolü üstlenmek istediğinde, bu ARN'yi ve External ID'yi kullanarak bir sts:AssumeRole çağrısı yapar.
  3. Güvenlik: External ID, burada SaaS'ın kendi içindeki kötü niyetli bir kullanıcının veya başka bir müşterinin, sizin hesabınızdaki rolü üstlenmeye çalışmasını engeller. Eğer SaaS platformu içindeki kötü niyetli bir aktör, sizin rolünüzü üstlenmeye çalışırsa ve doğru External ID'yi sağlayamazsa (çünkü bu External ID size özeldir ve sadece SaaS'ın güvenilir sunucuları tarafından kullanılmalıdır), istek reddedilir. Bu sayede, üçüncü taraf entegrasyonlarında bile, Confused Deputy saldırılarına karşı korunarak minimum yetkilendirme prensibi güçlendirilir.

Bu vaka analizleri, Harici Kimlik kullanımının sadece teknik bir gereklilik olmanın ötesinde, gerçek dünya güvenlik zorluklarına nasıl pratik ve etkili çözümler sunduğunu göstermektedir. AwsCustomResource ile bu tür senaryoları otomatikleştirmek, güvenli ve ölçeklenebilir bulut altyapıları oluşturmanın anahtarıdır.

İleri Düzey Güvenlik İpuçları ve En İyi Uygulamalar

Harici Kimlik (External ID) kullanımı, çapraz hesap operasyonlarında güvenliği artırmanın temel bir adımıdır. Ancak, bu mekanizmadan en iyi şekilde faydalanmak ve genel güvenlik duruşunuzu daha da güçlendirmek için bazı ileri düzey ipuçları ve en iyi uygulamalar mevcuttur:

  1. Benzersiz ve Rastgele External ID'ler Kullanın: External ID'ler, uzun, karmaşık ve kriptografik olarak güçlü rastgele dizeler olmalıdır. Tahmin edilebilir veya kısa ID'ler, brute-force saldırılarına karşı savunmasız kalabilir. Her entegrasyon veya her hedef hesap için benzersiz bir External ID kullanmak, risk izolasyonunu artırır. Bir External ID sızarsa, diğer entegrasyonlar etkilenmez.
  2. External ID Rotasyonu: Tıpkı parolalar gibi, External ID'ler de düzenli olarak (örneğin, 90 günde bir) döndürülmelidir. Bu, olası bir sızıntının etki süresini kısaltır. Rotasyon, hedef roldeki Trust Policy'yi ve AwsCustomResource veya üçüncü taraf entegrasyonundaki yapılandırmayı güncellemeyi gerektirir. Bu işlemi otomatikleştirmek için AWS Secrets Manager gibi servisler kullanılabilir.
  3. Least Privilege (En Az Yetkilendirme) Prensibi: IAM rolleri için her zaman en az yetkilendirme prensibini uygulayın. Rollerin sadece yapması gereken minimum eylemler için izinleri olmalıdır. Örneğin, bir AwsCustomResource sadece bir S3 kovasına obje yazacaksa, ona tüm S3 izinlerini veya başka servislere erişim izinlerini vermeyin. Kaynakları da spesifikleştirin (örneğin, arn:aws:s3:::my-bucket/* yerine sadece belirli bir objeyi belirtin).
  4. Koşullu İzinler (Condition Keys) Kullanımı: sts:ExternalId'ye ek olarak, IAM Trust Policy'lerinde diğer koşul anahtarlarını da kullanarak güvenliği artırabilirsiniz. Örneğin:
    • aws:SourceIp: Rol üstlenme isteğinin belirli IP aralıklarından gelmesini zorunlu kılmak.
    • aws:SourceVpc veya aws:SourceVpce: İsteğin belirli bir VPC veya VPC Endpoint'ten gelmesini sağlamak.
    • aws:MultiFactorAuthPresent: MFA (Çok Faktörlü Kimlik Doğrulama) gerekliliği.
    • aws:PrincipalArn: Rolü üstlenecek prensibin tam ARN'sini belirterek daha dar bir yetkilendirme sağlamak.
  5. İzleme ve Denetleme: AWS CloudTrail ile tüm sts:AssumeRole çağrılarını izleyin. Bu günlükler, kimin ne zaman hangi rolü üstlendiğini ve External ID'nin sağlanıp sağlanmadığını gösterir. Anormal rol üstlenme girişimlerini veya başarısız denemeleri tespit etmek için CloudWatch metrikleri ve alarmları yapılandırın. AWS Security Hub ve GuardDuty gibi servisler de güvenlik olaylarını otomatik olarak algılamaya yardımcı olabilir.
  6. CloudFormation/CDK ile Otomasyon: External ID değerlerini manuel olarak yönetmek yerine, bunları CloudFormation parametreleri, SSM Parametre Mağazası veya AWS Secrets Manager kullanarak CDK/CloudFormation şablonlarınızla otomatikleştirebilirsiniz. Bu, ID'leri kod tabanınıza gömmekten daha güvenli bir yaklaşımdır. Özellikle Secrets Manager, rotasyon ve erişim kontrolü için güçlü yetenekler sunar.
  7. Hata Yönetimi ve Güvenli Çıkış: AwsCustomResource'unuzdaki Lambda kodunun, rol üstlenme veya diğer API çağrılarında oluşabilecek hataları güvenli bir şekilde ele aldığından emin olun. Hata durumlarında hassas bilgileri loglamaktan kaçının ve beklenmedik durumlar için uygun geri alma (rollback) mekanizmaları uygulayın.

Bu ileri düzey güvenlik ipuçları ve en iyi uygulamalar, Harici Kimlik kullanımını tamamlar ve AWS ortamınızın genel güvenlik duruşunu önemli ölçüde güçlendirir. Güvenlik, sürekli bir süreçtir ve bu prensipleri uygulayarak, çapraz hesap operasyonlarınızı daha sağlam ve dirençli hale getirebilirsiniz.

Sonuç: Hesaplar Arası Operasyonlarda Güvenliğin Önemi

AWS bulutunda ölçeklenebilir ve esnek mimariler tasarlarken, çoklu hesap stratejisi vazgeçilmez bir yapı taşıdır. Bu strateji, kaynak izolasyonu, maliyet kontrolü ve yönetilebilirlik açısından önemli avantajlar sunarken, beraberinde hesaplar arası operasyonların güvenliğiyle ilgili kritik zorlukları da getirir. Özellikle AwsCustomResource gibi otomasyon araçlarını kullanarak farklı hesaplarda kaynak yönetimi yaparken, güvenlik risklerini minimize etmek hayati önem taşır. Bu makale boyunca ele aldığımız Harici Kimlik (External ID) mekanizması, Confused Deputy saldırıları gibi karmaşık güvenlik tehditlerine karşı güçlü bir savunma hattı oluşturur.

Harici Kimlik, rol üstlenme isteklerine ek bir kimlik doğrulama katmanı ekleyerek, yetkili bir hizmetin kötü niyetli bir aktör tarafından manipüle edilmesini engeller. AwsCustomResource'lar aracılığıyla Harici Kimlik kullanımını entegre etmek, CloudFormation veya CDK ile dağıtılan altyapınızın sadece işlevsel değil, aynı zamanda güvenlik best practice'lerine uygun olmasını sağlar. Hedef hesapta rolün Trust Policy'sine sts:ExternalId koşulu eklemek ve kaynak hesaptaki AwsCustomResource'un bu External ID'yi doğru bir şekilde sağlamasını yapılandırmak, bu sürecin ana adımlarıdır. Gerçek dünya senaryoları, merkezi güvenlik yönetimi ve üçüncü taraf entegrasyonlarında Harici Kimliğin nasıl etkin bir şekilde kullanılabileceğini göstermiştir.

Unutulmamalıdır ki, güvenlik tek seferlik bir işlem değil, sürekli bir süreçtir. External ID'leri benzersiz, rastgele tutmak, düzenli olarak döndürmek, en az yetkilendirme prensibini uygulamak ve tüm rol üstlenme eylemlerini izlemek, güvenli bir AWS ortamının sürdürülmesi için kritik öneme sahiptir. AWS altyapınızı büyütürken ve otomasyon seviyenizi artırırken, güvenlik her zaman öncelikli olmalıdır. Harici Kimlik desteği ile AwsCustomResource kullanımını benimseyerek, hesaplar arası operasyonlarınızın sağlamlığını ve güvenliğini önemli ölçüde artırabilir, böylece bulut yolculuğunuzda daha güvende olabilirsiniz.

Sıkça Sorulan Sorular (SSS)

  • S: Harici Kimlik (External ID) neden sadece bir IAM Rolünün Trust Policy'sinde kullanılır ve kullanıcılar için kullanılmaz?

    C: External ID, özellikle otomatikleştirilmiş sistemler, üçüncü taraf hizmetler veya çapraz hesap otomasyonlarında "Confused Deputy" saldırısını önlemek için tasarlanmıştır. Bu senaryolarda, bir hizmetin (veya başka bir hesabın) başka bir hesaptaki bir rolü üstlenmesi söz konusudur. Kullanıcılar ise genellikle MFA gibi farklı kimlik doğrulama mekanizmaları kullanır ve doğrudan etkileşimde bulunurlar. External ID'nin temel amacı, rolü üstlenen tarafın "niyetini" doğrulamaktır.

  • S: External ID ile IAM rolü arasındaki fark nedir?

    C: IAM rolü bir kimliktir; belirli izinlere sahip geçici kimlik bilgileri sağlar ve belirli eylemleri gerçekleştirmesine izin verilir. External ID ise bu rolü üstlenme sürecine eklenen bir güvenlik koşuludur. Rolü üstlenme isteği yapanın, rolün Trust Policy'sinde tanımlanan spesifik bir gizli değeri sağlamasını zorunlu kılar. Rol, yetkiyi tanımlar; External ID, yetkiyi kimin üstlenebileceğine ek bir güvenlik katmanı ekler.

  • S: External ID yerine neden sadece AWS hesabı kimliği veya bir IAM kullanıcı/rol ARN'i Trust Policy'ye eklemiyoruz?

    C: Sadece AWS hesabı kimliği veya IAM ARN'i Trust Policy'ye eklemek, Confused Deputy saldırılarına karşı yeterli koruma sağlamaz. Kötü niyetli bir aktör, yetkili bir servisi (örneğin, bir AwsCustomResource) manipüle ederek, sizin hesabınızdaki rolü üstlenmesini sağlayabilir, çünkü servisin yetkilendirilmiş bir hesabın parçasıdır. External ID, bu durumu önler; çünkü kötü niyetli aktör, External ID'yi bilmediği için rolü üstlenme isteği başarısız olur.

  • S: Bir AwsCustomResource'da External ID'yi nasıl dinamik olarak yönetebilirim?

    C: External ID'yi kodunuza hardcode etmek yerine, AWS Secrets Manager veya SSM Parameter Store gibi hizmetlerde saklayıp, AwsCustomResource'un çalıştığı Lambda fonksiyonunun çalışma zamanında bu değeri çekmesini sağlayabilirsiniz. Bu, güvenlik ve yönetilebilirlik açısından en iyi uygulamadır. Ayrıca, CDK veya CloudFormation'a parametre olarak geçirmek de bir yöntemdir, ancak Secrets Manager daha güvenli rotasyon ve erişim kontrolü sağlar.

Yorumlar
İçeriği beğendiniz mi? Bir tartışma başlatın veya görüşlerinizi paylaşın.
Yorum Yaz

Bir yanıt yazın

E-posta adresiniz yayınlanmayacak. Gerekli alanlar * ile işaretlenmişlerdir

Gönder

E-posta Bülteni
Yazılım Topluluğuna Katılın
En son güncellemeleri, yaratıcı ipuçlarını ve özel kaynakları doğrudan e-posta kutunuza alın. Tasarım ve inovasyonun geleceğini birlikte keşfedelim.
Exit mobile version