Implementieren Sie schnell S3-kompatiblen Speicher mit Python-Flask

was ist das

Dies ist ein Artikel zum Erstellen eines S3-kompatiblen Speichers mit Python. Die Bedeutung des Studiums ist stark.

Entdecken Sie die Bewegung des Kunden

Nach einem kurzen Blick auf die offizielle AWS API-Dokumentation entschied ich mich herauszufinden, was der S3-Client tatsächlich tat.

Voraussetzungen

--Verwenden Sie Python & Flask für die Dummy-Server-App

Object Listing

127.0.0.1 - - [29/Jan/2017 01:02:24] "GET /test-bucket/?max-keys=1000&prefix&delimiter=%2F HTTP/1.1"

Operation-Präfix in GET-Abfrage angegeben, Einstellungen in Bezug auf Demilita-Die Wurzel des Buckets wird getroffen [Request-Header]
Authorization: AWS hogehoge_user1:ysH68SkszwcudzrtZAlxlV9z8WA=
Content-Length:
User-Agent: Cyberduck/4.7.2.18004 (Mac OS X/10.10.5) (x86_64)
Connection: upgrade
Host: b.tgr.tokyo
X-Amz-Request-Payer: requester
Date: Sun, 29 Jan 2017 01:02:23 GMT
Content-Type:

Upload

127.0.0.1 - - [29/Jan/2017 01:04:19] "PUT /test-bucket/gopher.png HTTP/1.1"

[Header anfordern]
Authorization: AWS hogehoge_user1:suTrxv+XQuecbq7vUMYoQ3rWBcM=
Content-Length: 114063
User-Agent: Cyberduck/4.7.2.18004 (Mac OS X/10.10.5) (x86_64)
Connection: upgrade
Host: b.tgr.tokyo
Date: Sun, 29 Jan 2017 01:04:18 GMT
Content-Type: image/png

Download --Verwenden Sie die GET-Methode

127.0.0.1 - - [29/Jan/2017 01:05:09] "GET /test-bucket/gopher.png HTTP/1.1"

[Header anfordern]
Authorization: AWS hogehoge_user1:rhqMjHlbcYg/APr7bv9PH7tbyy4=
Content-Length:
User-Agent: Cyberduck/4.7.2.18004 (Mac OS X/10.10.5) (x86_64)
Connection: upgrade
Host: b.tgr.tokyo
X-Amz-Request-Payer: requester
Date: Sun, 29 Jan 2017 01:05:09 GMT
Content-Type:

Delete --Verwenden Sie die DELETE-Methode

127.0.0.1 - - [29/Jan/2017 01:05:59] "DELETE /test-bucket/gopher.png HTTP/1.1"

[Header anfordern]
Authorization: AWS hogehoge_user1:U2NEDsKLvJ08mLYdPIB43R+IAu0=
Content-Length:
User-Agent: Cyberduck/4.7.2.18004 (Mac OS X/10.10.5) (x86_64)
Connection: upgrade
Date: Sun, 29 Jan 2017 01:05:59 GMT
Host: b.tgr.tokyo
Content-Type:

Impressionen

Es ist ziemlich erfrischend, wenn Sie also einen APP-Server mit den folgenden Funktionen schreiben Es scheint, dass Sie S3 erstellen können, auf das von Cyberduck aus zugegriffen werden kann.

--Überprüfen Sie den Authorization-Header und autorisieren Sie (allen Anforderungen gemeinsam)

Implementieren

Obwohl es sich um eine fertige Version handelt, habe ich sie auf simple-s3-clone verschoben. Den detaillierten Code finden Sie hier. Es gibt kein Konzept für einen Bucket, und die Fehlerbehandlung ist immer noch gut, daher werde ich sie später hinzufügen.

Der in der folgenden Erläuterung angezeigte Code wurde zur Erläuterung entfernt. Ich hoffe, das Konzept alleine zu vermitteln.

Authentifizierungsteil

Hier hatte ich die meisten Probleme. Grundsätzlich authentifiziere ich mich wie folgt, habe jedoch die Existenz des X-Amz-Headers vergessen und war frustriert, weil er nicht für immer mit der vom Client generierten Signatur übereinstimmte.

--Erstellen Sie eine Signaturgenerierungszeichenfolge (diese Zeichenfolge kann aus der Anforderungsmethode, dem Pfad und den Headerinformationen generiert werden.)


def get_x_amz_headers():
    return filter(lambda x: x[0].startswith('X-Amz-'), request.headers.items())

def generate_x_amz_string():
    ret = ''
    #X, um eine Zeichenfolge für die Authentifizierung zu generieren-Amz-Header sortieren und verketten
    for key in sorted(get_x_amz_headers()):
        k = key[0].lower()
        v = request.headers.get(key[0])
        ret += '{}:{}\n'.format(k, v)
    return ret


def generate_auth_string():
    s = '{}\n{}\n{}\n{}\n{}{}'.format(
        request.method,
        request.headers.get('Content-Md5', ''),
        request.headers.get('Content-Type', ''),
        request.headers.get('Date', ''),
        generate_x_amz_string(),
        request.path
    )
    return s

def auth_check(auth_raw_string):
    auth_info = request.headers.get('Authorization')
    access_key_id = 'hogehoge_key_id'
    secret_access_key = 'hogehoge_secret'
    # HMAC-SHA-Verwenden Sie 1, um die generierte Zeichenfolge mit einem geheimen Schlüssel zu hashen(Signaturerstellung)
    hashed = hmac.new(secret_access_key, auth_raw_string,
                      hashlib.sha1).digest()
    #Die Form des vom Benutzer gesendeten Authentifizierungsheaders(AWS AccessKeyID:Signature)machen
    generated_signature = 'AWS {}:{}'.format(
        access_key_id, base64.encodestring(hashed).rstrip())
    #Vergleichen Sie mit der vom Benutzer generierten Signatur
    if auth_info != generated_signature:
        raise exception.SignatureDoesNotMatch()


@app.before_request
def before_request():
    #Authentifizieren Sie sich vor jeder Anfrage
    s = generate_auth_string()
    auth_check(s)

Objektliste und Download

@app.route("/<path:path>")
def get_request_with_path(path):
    if g.resource_path == '':
        return process_object_list()
    else:
        return download_object()

Objekt hochladen, Ordner erstellen

@app.route("/<path:path>", methods=['PUT'])
def put_request_with_path(path):
    if int(request.headers.get('Content-Length')) != len(request.data):
        raise exception.MissingContentLength()
    if g.resource_path[-1] == '/':
        return create_prefix()
    else:
        return create_object()

Objekte löschen, Ordner löschen


@app.route("/<path:path>", methods=['DELETE'])
def delete_request_with_path(path):
    if g.resource_path[-1] == '/':
        return delete_prefix()
    else:
        return delete_object()

Es scheint sich zu bewegen

simple-s3-clone.gif

s3cmd funktionierte nicht, da sich die Art und Weise, wie die Anfrage gesendet wurde, von der von cyberduck unterschied. Wenn Sie jedoch den Authentifizierungsteil ändern, können Sie anscheinend sofort antworten.

Schließlich

Bis jetzt habe ich wissenschaftliche und technologische Berechnungen wie Simulationen durchgeführt, aber nach meinem Eintritt in das Unternehmen habe ich etwas über Dienstleistungen wie S3 gelernt Diese Motivation ist, dass ich die Serverseite implementieren wollte.

Referenzseite

Recommended Posts

Implementieren Sie schnell S3-kompatiblen Speicher mit Python-Flask
Mit Pandas schnell visualisieren
Implementieren Sie FReLU mit tf.keras
S3 Uploader mit Boto