Newer
Older
import { ReactNode, createContext, useContext, useState } from "react";
import { useOAuth } from "./OAuth2";
import { STSClient, AssumeRoleWithWebIdentityCommand } from "@aws-sdk/client-sts";
import { S3Client } from "@aws-sdk/client-s3";
import { AwsCredentialIdentity } from "@aws-sdk/types";
import { useCallback } from "react";
import { useEffect } from "react";
// **** AWS Config ****
export interface AWSConfig {
region: string;
}
// ***** State *****
export interface IS3ServiceState {
awsCredentials?: AwsCredentialIdentity;
}
export const initialS3ServiceState: IS3ServiceState = {
}
// ***** Context *****
export interface S3ContextProps {
awsConfig: AWSConfig;
client: S3Client;
isAuthenticated: () => boolean;
}
export const S3ServiceContext = createContext<S3ContextProps | undefined>(undefined);
// ***** S3Service *****
interface S3ServiceProviderProps {
awsConfig: AWSConfig;
children?: ReactNode;
}
export const S3ServiceProvider = (props: S3ServiceProviderProps): JSX.Element => {
const { children, awsConfig } = props;
const [
s3ServiceState,
setS3ServiceState
] = useState<IS3ServiceState>(initialS3ServiceState);
const oAuth = useOAuth();
const { awsCredentials } = s3ServiceState;
// Factory method
const getS3Client = useCallback(() => {
return new S3Client({
Jacopo Gasparetto
committed
endpoint: awsConfig.endpoint,
region: awsConfig.region,
credentials: awsCredentials,
forcePathStyle: true
});
}, [awsCredentials, awsConfig.endpoint]);
const isAuthenticated = () => {
return oAuth.isAuthenticated && !!awsCredentials;
}
// Exchange token for AWS Credentiasl with AssumeRoleWebIdendity
useEffect(() => {
if (!(oAuth.isAuthenticated && token)) {
console.log("Token missig or expired");
return;
}
const sts = new STSClient({ ...awsConfig });
const command = new AssumeRoleWithWebIdentityCommand({
DurationSeconds: 3600,
RoleArn: "arn:aws:iam:::role/S3AccessIAM200",
RoleSessionName: "ceph-frontend-poc", // TODO: change me
WebIdentityToken: token.access_token,
});
sts.send(command)
.then(response => {
const { Credentials } = response;
if (!Credentials) {
throw new Error("Credentials not found");
}
const { AccessKeyId, SecretAccessKey, SessionToken } = Credentials;
if (AccessKeyId && SecretAccessKey && SessionToken) {
setS3ServiceState({
awsCredentials: {
accessKeyId: AccessKeyId,
secretAccessKey: SecretAccessKey,
sessionToken: SessionToken
}
});
} else {
console.warn("Warning: some one or more AWS Credentials member is empty");
}
}).catch(err => {
console.error("Cannot retrieve AWS Credentials from STS", err);
});
}, [awsConfig, oAuth.isAuthenticated, oAuth.user]);
return (
<S3ServiceContext.Provider value={{
awsConfig: awsConfig,
client: getS3Client(),
isAuthenticated: () => isAuthenticated()
}}>
{children}
</S3ServiceContext.Provider>
);
}
// **** useS3Service *****
export const useS3Service = (): S3ContextProps => {
const context = useContext(S3ServiceContext);
if (!context) {
throw new Error(
"S3ServiceProvider context is undefined, " +
"please verify you are calling useS3Service " +
"as a child of <S3ServicePrivder> comonent."
);
}
return context;
}