Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Support pre-signed URLs #157

Merged
merged 1 commit into from
Feb 14, 2025
Merged

Conversation

machacekondra
Copy link
Collaborator

This feauture is built on top of:
https://github.com/openshift/assisted-service/blob/master/docs/enhancements/image-service-cloud-authentication.md https://github.com/openshift/assisted-service/blob/master/docs/enhancements/short-url-enhancement.md

The flow to get URL:

GET http://{service}/api/v1/sources/{source-id}/image-url

This will generate the URL which could be used for 4hours by user to download the OVA, then the token will be invalidated.

Each source keep private key to sign&verify the URL token.

@app-sre-bot
Copy link
Collaborator

Can one of the admins verify this patch?

@machacekondra machacekondra force-pushed the presigned branch 2 times, most recently from d001eb4 to 318bc18 Compare February 12, 2025 14:43
@@ -147,8 +147,9 @@ deploy-on-kind:
deploy/k8s/migration-planner.yaml.template > deploy/k8s/migration-planner.yaml
$(KUBECTL) apply -n "${MIGRATION_PLANNER_NAMESPACE}" -f 'deploy/k8s/*-service.yaml'
$(KUBECTL) apply -n "${MIGRATION_PLANNER_NAMESPACE}" -f 'deploy/k8s/*-secret.yaml'
@config_server=$$(ip addr show ${IFACE}| grep -oP '(?<=inet\s)\d+\.\d+\.\d+\.\d+'); \
$(KUBECTL) create secret generic migration-planner-secret -n "${MIGRATION_PLANNER_NAMESPACE}" --from-literal=config_server=http://$$config_server:7443 --from-literal=config_server_ui=https://$$config_server_ui/migrate/wizard || true
config_server=$$(ip addr show ${IFACE}| grep -oP '(?<=inet\s)\d+\.\d+\.\d+\.\d+'); \
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In follow up PR we need to refactor the names and env vars.

@machacekondra machacekondra marked this pull request as ready for review February 13, 2025 10:09
ImageExpirationTime = 4 * time.Hour
)

func GenerateShortImageDownloadURLByToken(baseUrl string, source *model.Source) (string, *strfmt.DateTime, error) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm not nit-picking here but the func name could be much simpler. What does "ShortImage" mean in this context? :)

Copy link
Collaborator Author

@machacekondra machacekondra Feb 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So renaming to: GenerateDownloadURLByToken

return token.SignedString(key)
}

func ParseExpirationFromToken(tokenString string) (*strfmt.DateTime, error) {
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

FromToken is useless and tokenString could be token.
i know but I couldn't help myself. :)

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Well the tokenString makes sense in method because then we call:
token, _, err := new(jwt.Parser).ParseUnverified(token, jwt.MapClaims{})
to get jwt.Token and that we name the token, I think it nicely says what is what
but I will remove FromToken for sure

func ValidateToken(token string, keyFunc func(token *jwt.Token) (interface{}, error)) error {
parsedToken, err := jwt.Parse(token, keyFunc)
if err != nil {
return fmt.Errorf("Unauthorized")
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

it would be nice to have an error here to be able to add more context in the caller body. Like for which source id was this

return server.GetImageByToken401JSONResponse{Message: "error creating the HTTP stream"}, nil
}

ova := &image.Ova{SshKey: source.SshPublicKey, SourceID: source.ID, Writer: writer}
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

please use the builder here. this is obsolete

}

// TODO: How to add the pull secret???
size, err := imageBuilder.Generate(ctx, writer)
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should add a new option to the builder WithPullSecret

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yup, but we don't have it...

return &ServiceHandler{
store: store,
eventWriter: ew,
cfg: cfg,
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Why do you need cfg here?

Copy link
Collaborator Author

@machacekondra machacekondra Feb 13, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So I can take Image URL from config.yaml in case env var is not set. This needs refactoring, I put TODO in code, I will do it in follow up PR.

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

but we have a new service now. I don't see where this var is used in this service.

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

https://github.com/kubev2v/migration-planner/pull/157/files#diff-662d8d27575cdd81927622a394d6c33a358b38f9de49c2dc594d5b7739131eb0R36

The hostname of the image service is defined either in MIGRATION_PLANNER_URL or in config.yaml

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ah, only now I see it's wrong service, you are right, removing....

@machacekondra machacekondra force-pushed the presigned branch 3 times, most recently from 01b4be3 to bf7bfe2 Compare February 13, 2025 19:32
This feauture is built on top of:
https://github.com/openshift/assisted-service/blob/master/docs/enhancements/image-service-cloud-authentication.md
https://github.com/openshift/assisted-service/blob/master/docs/enhancements/short-url-enhancement.md

The flow to get URL:

GET http://{service}/api/v1/sources/{source-id}/image-url

This will generate the URL which could be used for 4hours by user to download the OVA,
then the token will be invalidated.

Each source keep private key to sign&verify the URL token.

Signed-off-by: Ondra Machacek <omachace@redhat.com>
@machacekondra machacekondra merged commit dfed5cf into kubev2v:main Feb 14, 2025
4 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants