Cloudfront'ta statik olarak barındırılan bir web sitesi için alt dizinler için varsayılan bir kök nesneyi nasıl ayarlarsınız?


104

Cloudfront'ta statik olarak barındırılan bir web sitesinde alt dizinler için varsayılan bir kök nesneyi nasıl ayarlarsınız? Özellikle, www.example.com/subdir/index.htmlkullanıcı ne zaman isterse size hizmet edilmesini istiyorum www.example.com/subdir. Bunun, bir S3 klasöründe tutulan statik bir web sitesini sunmak için olduğunu unutmayın. Ek olarak, S3 klasörüne erişimi yalnızca Cloudfront ile kısıtlamak için bir kaynak erişim kimliği kullanmak istiyorum.

Şimdi, Cloudfront'un özellikle S3 ve amazon eyaletlerinden farklı çalıştığını biliyorum :

CloudFront varsayılan kök nesnelerinin davranışı, Amazon S3 dizin belgelerinin davranışından farklıdır. Bir Amazon S3 klasörünü web sitesi olarak yapılandırdığınızda ve dizin belgesini belirttiğinizde, Amazon S3, kullanıcı grupta bir alt dizin talep etse bile dizin belgesini döndürür. (Dizin belgesinin bir kopyası her alt dizinde görünmelidir.) Amazon S3 paketlerini web sitesi olarak yapılandırma ve dizin belgeleri hakkında daha fazla bilgi için Amazon Simple Storage Service Geliştirici Kılavuzu'ndaki Amazon S3'te Web Sitelerini Barındırma bölümüne bakın.

Bunun gibi, CloudFront varsayılan bir kök nesne belirtmek için bize imkan verse dahi, bu sadece çalışır www.example.comve değil www.example.com/subdir. Bu zorluğun üstesinden gelmek için, kaynak alan adını S3 tarafından verilen web sitesi uç noktasına işaret edecek şekilde değiştirebiliriz. Bu harika çalışıyor ve kök nesnelerin tek tip olarak belirlenmesine izin veriyor. Maalesef bu, kaynak erişim kimlikleriyle uyumlu görünmüyor . Özellikle yukarıdaki bağlantılar şunları belirtir:

Düzenleme moduna geçin:

Web dağıtımları - Kökenler sekmesini tıklayın, düzenlemek istediğiniz kaynağı tıklayın ve Düzenle'yi tıklayın. Yalnızca Origin Type'ın S3 Origin olduğu kaynaklar için bir kaynak erişim kimliği oluşturabilirsiniz.

Temel olarak, doğru varsayılan kök nesnesini ayarlamak için web sitesi paketinin kendisini değil, S3 web sitesi uç noktasını kullanırız. Bu, kaynak erişim kimliğinin kullanılmasıyla uyumlu değildir. Bu nedenle, sorularım ikisine de

  1. Cloudfront'ta statik olarak barındırılan bir web sitesi için tüm alt dizinler için varsayılan bir kök nesne belirtmek mümkün müdür?

  2. Kaynağın S3 web sitesi uç noktası olduğu ve S3 klasörünün olmadığı Cloudfront'tan sunulan içerik için bir kaynak erişim kimliği ayarlamak mümkün müdür?


1
Bunun artık /index.html ile biten tüm URL'leri yeniden yönlendiren bir işlev kullanılarak Lambda @ edge ile yapılabileceğini düşünüyorum. Bunu web sitemde deneyeceğim ve sonuçları geri bildireceğim ve ayrıntılı yapılandırmayı bir yanıt olarak göndereceğim.
Cristian Măgherușan-Stanciu

Yanıtlar:


2

GÜNCELLEME: Görünüşe göre yanılmışım! JBaczuk'un bu konudaki kabul edilen cevabı olması gereken cevabına bakın.

Ne yazık ki, her iki sorunuzun da cevabı hayır.

1. Cloudfront'ta statik olarak barındırılan bir web sitesi için tüm alt dizinler için varsayılan bir kök nesne belirtmek mümkün müdür?

Hayır. AWS CloudFront belgelerinde belirtildiği gibi ...

... Varsayılan bir kök nesnesi tanımlarsanız, dağıtımınızın bir alt dizini için son kullanıcı isteği varsayılan kök nesnesini döndürmez. Örneğin, index.htmlvarsayılan kök nesnenizin olduğunu ve CloudFront'un CloudFront dağıtımınız altındaki yükleme dizini için bir son kullanıcı isteği aldığını varsayalım :

http://d111111abcdef8.cloudfront.net/install/

CloudFront index.html, kurulum dizininde bir kopyası görünse bile varsayılan kök nesnesini döndürmez .

...

CloudFront varsayılan kök nesnelerinin davranışı, Amazon S3 dizin belgelerinin davranışından farklıdır. Bir Amazon S3 klasörünü web sitesi olarak yapılandırdığınızda ve dizin belgesini belirttiğinizde, Amazon S3, kullanıcı grupta bir alt dizin talep etse bile dizin belgesini döndürür. (Her alt dizinde dizin belgesinin bir kopyası görünmelidir.)

2. Kaynağın bir S3 klasöründen ziyade bir S3 web sitesi uç noktası olduğu Cloudfront'tan sunulan içerik için bir kaynak erişim kimliği ayarlamak mümkün müdür?

Dolaylı. CloudFront ile başlangıç ​​seçenekleriniz S3 kovaları veya kendi sunucunuzdur.

Yine de, bazı ilginç olasılıkları açan bu ikinci seçenek. Bu muhtemelen yapmaya çalıştığınız şeyin amacını ortadan kaldırır, ancak tek görevi bir CloudFront kaynak sunucusu olmak olan kendi sunucunuzu kurabilirsiniz.

Http://d111111abcdef8.cloudfront.net/install/ için bir istek geldiğinde , CloudFront bu isteği kaynak sunucunuza ileterek isteyerek gönderir /install. Kaynak sunucunuzu index.html, bu durumda hizmet vermek de dahil olmak üzere istediğiniz şekilde yapılandırabilirsiniz .

Ya da bu çağrıyı alan ve yine de doğrudan S3'ten alan küçük bir web uygulaması yazabilirsiniz.

Ancak, kendi sunucunuzu kurmanın ve onu ölçeklendirme konusunda endişelenmenin, ilk başta yapmaya çalıştığınız şeyin amacını bozabileceğinin farkındayım.


Bununla ilgili sahip olduğum tek sorun, bunun işe yaramasıdır, web sitenize s3'te erişebileceğiniz iki (2) URL'ye sahip olmanızdır. Bulut ön URL'niz ve s3 url'niz (kova_adı.s3-website-us-east-1.amazonaws.com)
Hayden

226

Orada IS bunu yapmanın bir yolu. Açılır listeden (www.example.com.s3.amazonaws.com) seçerek paketinize işaret etmek yerine, onu grubunuzun statik etki alanına (ör. Www.example.com.s3-website-us -west-2.amazonaws.com):

görüntü açıklamasını buraya girin

Bu AWS Forumu başlığına teşekkürler


6
Bir s3 kökenine karşı bir web kaynağına sahipken bunun farklı ücretler olup olmadığını bilen var mı?
fideloper

3
Tüm web sitemi ve dosyalarımı HTTPSyalnızca üzerinden sunmak istersem bu iyi çalışıyor mu ?
Manjit Kumar

3
S3'ün bir web sunucusu olarak etkinleştirilmesi gerektiği anlamına mı geliyor?
Anthony Kong

6
OP, bu yaklaşımın kendisi için işe yaramayacağını açıkça belirtti: "Bu zorluğun üstesinden gelmek için, kaynak alan adını S3 tarafından verilen web sitesi uç noktasına işaret edecek şekilde değiştirebiliriz. Bu harika çalışıyor ve kök nesnelerin tek tip olarak belirlenmesine izin veriyor. Ne yazık ki , bu, kaynak erişim kimlikleriyle uyumlu görünmüyor ". AWS'nin kendisi
icyitscold

4
Bu uyumlu Cloud Front - Origin Access Identity değil. S3 klasörünüze erişimi bu şekilde kısıtlayamazsınız.
rocketspacer

16

S3 barındırma hizmetinin etkinleştirilmesi, kovayı dünyaya açmanız gerektiği anlamına gelir. Benim durumumda, paketi gizli tutmam ve yalnızca Cloudfront'a erişimi kısıtlamak için kaynak erişim kimliği işlevini kullanmam gerekiyordu. @ Juissi'nin önerdiği gibi, bir Lambda işlevi yönlendirmeleri düzeltebilir:

'use strict';

/**
 * Redirects URLs to default document. Examples:
 *
 * /blog            -> /blog/index.html
 * /blog/july/      -> /blog/july/index.html
 * /blog/header.png -> /blog/header.png
 *
 */

let defaultDocument = 'index.html';

exports.handler = (event, context, callback) => {
    const request = event.Records[0].cf.request;

    if(request.uri != "/") {
        let paths = request.uri.split('/');
        let lastPath = paths[paths.length - 1];
        let isFile = lastPath.split('.').length > 1;

        if(!isFile) {
            if(lastPath != "") {
                request.uri += "/";
            }

            request.uri += defaultDocument;
        }

        console.log(request.uri);
    }

    callback(null, request);
};

İşlevinizi yayınladıktan sonra, AWS konsolunda cloudfront dağıtımınıza gidin. Git Behaviorsseçin.LI_CLOSE Origin Requestaltında Lambda Function Associationsve son olarak yeni fonksiyona ARN yapıştırın.


5
Buna benzer bir lambda işlevi dağıtmaya hazır: serverlessrepo.aws.amazon.com/applications/…
marcanuy

Buradaki sorun, bu işlevin us-east-1'e dağıtılması gerektiğidir, bu nedenle, Almanya dışında tek bir bitlik izin vermeyen katı GDPR yönetmeliğine sahip bir şirketiniz varsa, bu sizin için değildir.
Renato Gama

6

Bir alt dizinde sunulan varsayılan bir dosyayı almanın başka bir yolu vardır, örneğin example.com/subdir/. Paket içindeki anahtarla bir dosyayı aslında (programlı olarak) depolayabilirsiniz subdir/. Bu dosya olacak değil S3 yönetim konsolunda göstermek, ama aslında var ve CloudFront bunu görev yapacak.


S3 yakınsama alt dizini / alt dizine; HTML'yi yüklemeye çalıştığınızda. Ayrıca, example.com/subdir/ adresine erişmeye çalıştığınızda başarısız olur ve example.com/subdir'e erişmeye çalışırsanız; oluşturmak yerine HTML dosyasını indirir.
jacobfogg

Bu aslında bulduğum en iyi yaklaşımlardan biri, çünkü belirli bir konfigürasyon olmadan tüm S3 dağıtımlarında çalışıyor ve lambda @ edge kullanması gerekiyor (bu, lambda yürütülürken sayfalara hizmet vermeyi yavaşlatan ve fazladan yönlendirme oluşturan). @Jacobfogg yorumuna katılmıyorum. Programlı olarak kullanıldığında mükemmel bir şekilde çalışır. Bir S3 olayı tarafından tetiklenen küçük bir lambda işlevi yaptım. Aşağıdaki cevabıma bakın.
Jeremie

4

Sorun için geçici çözüm, istekleri yeniden yazmak için lambda @ edge kullanmaktır. CloudFront dağıtımının görüntüleyici istek olayı için lambda'nın ayarlanması ve '/' VE ile biten her şeyi varsayılan kök belge, örneğin index.html ile '/' ile yeniden yazması yeterlidir.


Bu yaklaşımla ilgili daha fazla ayrıntı burada: aws.amazon.com/blogs/compute/…
Henrik Aasted Sørensen

maalesef Lambda @ Edge yalnızca us-doğu-1 bölgesinde çalışır, kaynak: github.com/awslabs/serverless-application-model/issues/635
mruanova

4

Bir yoktur AWS blogda yayınlanan "resmi" rehber sizin CloudFront dağılımı tarafından tetiklenen bir Lambda @ Kenar işlevini kurma önerir:

Elbette, kullanıcılardan her URL'nin sonuna index.html yazmalarını (veya orada olması gerektiğini bile bilmelerini) beklemek kötü bir kullanıcı deneyimidir. Şimdiye kadar, kullanıcılara bu basit URL'leri (Apache Web Sunucusu yapılandırmasındaki DirectoryIndex Direktifine eşdeğer) CloudFront aracılığıyla sağlamanın kolay bir yolu yoktu. Yine de bir OAI kullanarak S3 kaynağına erişimi kısıtlayabilmek istiyorsanız değil. Bununla birlikte, Lambda @ Edge'in piyasaya sürülmesiyle, bu kalıpları aramak ve S3 kaynağından uygun nesne anahtarını talep etmek için CloudFront uç düğümlerinde çalışan bir JavaScript işlevini kullanabilirsiniz.

Çözüm

Bu örnekte, isteği istemciden gelirken incelemek için CloudFront kenarındaki işlem gücünü kullanırsınız. Ardından isteği yeniden yazın, böylece CloudFront, '/' ile biten herhangi bir istek URI'si için varsayılan bir dizin nesnesi (bu durumda index.html) talep eder.

Bir web sunucusuna karşı bir talep yapıldığında, istemci talepte elde edilecek nesneyi belirtir. Bu URI'yi kullanabilir ve ona normal bir ifade uygulayabilirsiniz, böylece bu URI'ler, CloudFront nesneyi başlangıç ​​noktasından istemeden önce bir varsayılan dizin nesnesine çözümlenir. Aşağıdaki kodu kullanın:

'use strict';
exports.handler = (event, context, callback) => {

    // Extract the request from the CloudFront event that is sent to Lambda@Edge
    var request = event.Records[0].cf.request;

    // Extract the URI from the request
    var olduri = request.uri;

    // Match any '/' that occurs at the end of a URI. Replace it with a default index
    var newuri = olduri.replace(/\/$/, '\/index.html');

    // Log the URI as received by CloudFront and the new URI to be used to fetch from origin
    console.log("Old URI: " + olduri);
    console.log("New URI: " + newuri);

    // Replace the received URI with the URI that includes the index page
    request.uri = newuri;

    // Return to CloudFront
    return callback(null, request);

};

S3 demeti, CloudFront dağıtımı ve Lambda @ Edge işlevi oluşturma dahil olmak üzere bunu ayarlamak için gereken tüm adımları görmek için yukarıda bağlantısı verilen kılavuzu izleyin .


2

Lambda @ edge kullanmanın başka bir alternatifi, CloudFront'un hata sayfalarını kullanmaktır. Tüm 403'leri belirli bir dosyaya göndermek için Özel Hata Yanıtı oluşturun. Ardından, index.html'yi / ile biten url'lere eklemek için bu dosyaya javascript ekleyin. Basit kod:

if ((window.location.href.endsWith("/") && !window.location.href.endsWith(".com/"))) {
    window.location.href = window.location.href + "index.html";
}
else {
    document.write("<Your 403 error message here>");
}

1

Bunun eski bir soru olduğunu biliyorum, ama bunun üstesinden kendim geçtim. Nihayetinde amacım, bir dizinde varsayılan bir dosya ayarlamaktan çok, sonunda olmadan sunulan bir dosyanın nihai sonucunu elde etmekti .html.

.htmlDosya adından kaldırdım ve mime türünü programlı / manuel olarak ayarladım text/html. Bu geleneksel yol değil, ancak işe yarıyor gibi görünüyor ve bulut formasyonunun faydalarından ödün vermeden güzel URL'ler için gereksinimlerimi karşılıyor. Mime türünü belirlemek can sıkıcı, ancak bence faydalar için ödenmesi gereken küçük bir bedel


0

@ johan-gorter, CloudFront'un / ile biten anahtarlara sahip dosya sunduğunu belirtti. İncelemeden sonra, bu seçeneğin işe yaradığı ve bu tür dosyaların S3'te programlı olarak oluşturulabileceği görülüyor. Bu nedenle, S3'te index.html veya index.htm sonekiyle bir dosya oluşturulduğunda tetiklenen küçük bir lambda yazdım.

Yaptığı şey bir nesne kopyalama olduğu dir/subdir/index.htmlbir nesne halinedir/subdir/

import json
import boto3

s3_client = boto3.client("s3")

def lambda_handler(event, context):

    for f in event['Records']:

        bucket_name = f['s3']['bucket']['name']
        key_name = f['s3']['object']['key']
        source_object = {'Bucket': bucket_name, 'Key': key_name}

        file_key_name = False

        if key_name[-10:].lower() == "index.html" and key_name.lower() != "index.html":
            file_key_name = key_name[0:-10]
        elif key_name[-9:].lower() == "index.htm" and key_name.lower() != "index.htm":
            file_key_name = key_name[0:-9]
        
        if file_key_name:
            s3_client.copy_object(CopySource=source_object, Bucket=bucket_name, Key=file_key_name)
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.