Git Product home page Git Product logo

aws-codeartifact-maven-proxy's Introduction

AWS CodeArtifact Maven Proxy

aws codeartifact maven proxy

This project contains a lightweight, embeddable proxy server for AWS CodeArtifact Maven repositories. It automatically handles endpoint lookups and CodeArtifact authorization tokens.

Background

AWS CodeArtifact is a great, cost-efficient service for hosting private Maven repositories. However, its authentication mechanism with its temporary tokens, while certainly adding a degree of security, is often cumbersome to work with:

  • Developers running a build from their local machine will have to install the AWS CLI and execute some commands to look up endpoints and retrieve authorization tokens.

  • Access to the repositories is only actually needed for the initial build execution and when dependencies have changed. For the majority of builds, the required artifacts can be served from a local cache, making it unnecessary to even obtain an authorization token.

How It Works

The proxy server is intended for local use only. It acts as a virtual Maven repository server by forwarding URL paths that conform to the pattern

/<domain>/<domain-owner>/<repo>/<group>/<artifact>/...

to the appropriate AWS CodeArtifact repository endpoint for domain, domain-owner and repo.

💡
The special value default can be used for the <domain-owner> to use the default AWS account ID based on the proxy server’s AWS credentials.
Example 1. Fowarding example

For example, assuming that the account 123456789012 has a CodeArtifact domain my-domain containing a repository my-repo in the region eu-west-1, the proxy server forwards the request

GET /my-domain/123456789012/my-repo/com/example/my-package/1.2.3/my-package-1.2.3.jar

to

https://my-domain-123456789012.d.codeartifact.eu-west-1.amazonaws.com/maven/my-repo/com/example/my-package/1.2.3/my-package-1.2.3.jar

The forwarded request will also contain an appropriate Authorization header containing

It uses the standard AWS SDK authentication strategies (e.g., AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY environment variables). The AWS APIs are only called on demand.

Authorization tokens are cached for the duration indicated by the AWS CodeArtifact API (maximum 12 hours). After that, the proxy server will automatically request a new token. To the user of the proxy server, this is completely transparent.

Caching is in-memory only, so cached tokens are lost when the proxy server is shut down or restarted. There is no disk cache, both for security reasons and because the proxy’s own AWS credentials might change between runs, making validation of cache entries about as expensive as just requesting new tokens.

Usage

As Embedded Server (JVM)

Prerequisites

  • JDK 1.8+

  • Kotlin: The server library is written in Kotlin and compiled against the Kotlin stdlib 1.5.20. If your code uses a different version of Kotlin, there might be some compatibility issues.

Steps

  • Include the artifact on your classpath:

    Maven (pom.xml)
    <dependency>
      <groupId>org.unbroken-dome.aws-codeartifact-maven-proxy</groupId>
      <artifactId>aws-codeartifact-maven-proxy</artifactId>
      <version>0.3.0</version>
    </dependency>
    Gradle (build.gradle / build.gradle.kts)
    dependencies {
        implementation("org.unbroken-dome.aws-codeartifact-maven-proxy:aws-codeartifact-maven-proxy:0.3.0")
    }

    The artifact is available on Maven Central.

  • Create an instance of Options

  • Call CodeArtifactMavenProxyServer.start(options), which returns a CompletableFuture to the server object allowing to stop it later. Synchronous/blocking variants startSync and stopSync are available as well.

  • The port can be configured in the Options, or set to 0 (default) to assign a random port. In the latter case, the actual port on which the server is listening can be queried using the actualPort property.

Using the CLI

  • Download the latest aws-codeartifact-maven-proxy-cli archive from the releases page and extract it

  • Run ./aws-codeartifact-maven-proxy to start the server. Ctrl+C to stop.

If started without any arguments, the server will start listening on a random port, which can be retrieved from the logs.

The following command-line arguments are available:

Option Description

--bind <address>

-b <address>

Bind to the given address instead of localhost / 127.0.0.1.

--port <port>

-p <port>

Local port to listen on. Set to 0 to choose a random port.

--debug

Show DEBUG-level logs.

--aws-debug

Show DEBUG-level logs for the AWS SDK.

--token-ttl <duration>

-t <duration>

TTL to request for authorization tokens from AWS CodeArtifact. This can be specified as a number of seconds (e.g. 300) or as a duration string like 1h30m.

A value of 0 (zero) will set the expiration of the authorization token to the same expiration of the user’s role’s temporary credentials.

If not set, uses the defaults of the service (currently 12 hours).

--endpoint-ttl <duration>

TTL for caching AWS CodeArtifact repository endpoints. By default, these will be cached indefinitely (until the server is stopped).

--eager-init

If this flag is used, certain setup tasks (like initializing the AWS clients) are done when the server starts. By default, all initialization is done lazily when it is actually needed, i.e. on the first request.

--wiretap [ all | targets ]

Specify a list of targets to enable "wiretap" logging on TRACE level. Valid targets are raw, http and ssl.

Multiple targets can be specified as a comma-separated list, e.g. --wiretap raw,http.

The value all (or just --wiretap) will enable wiretap logging for all targets.

Using a Docker image

Currently, the Docker image is not published to a public registry, but you can easily create it on your local Docker host with:

./gradlew :cli:jibDockerBuild

The environment variables or files for the desired AWS authentication strategy must be passed to the Docker image, and the port should be forwarded to the host. (Remember to bind to 127.0.0.1 on the host, otherwise the server will be public in your network!)

export AWS_ACCESS_KEY_ID=...
export AWS_SECRET_ACCESS_KEY=...
export AWS_REGION=...

docker run -d --name aws-codeartifact-maven-proxy \
  -e AWS_ACCESS_KEY_ID -e AWS_SECRET_ACCESS_KEY -e AWS_REGION \
  -p 127.0.0.1:8080:8080 \
  unbroken-dome:aws-codeartifact-maven-proxy:<version> -b 0.0.0.0 -p 8080

Other CLI arguments can be used as described above.

aws-codeartifact-maven-proxy's People

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

aws-codeartifact-maven-proxy's Issues

can you add more details on how to use this?

a pretty nifty piece of software, congratulations.

I'm a bit confused on how you use this once you standup the proxy. do you add the proxy host and port in maven settings.xml (or cmd line) like this? so it works as an actual http proxy...

 <proxies>
    <proxy>
...

OR instead of pointing to https://codeartifact...amazonws.com you change the URL in settings.xml and point to the proxy and the proxy does all the forwarding and returns back the result?

hope the question makes sense

Periodic exception: java.util.NoSuchElementException: backend-response-forwarder

Periodically receiving the following Exception when the mavenproxy is attempting cleanup. I can't narrow down the scenario; consequently, I can't provide a test case. However, I suggest first checking for the presence of the channel handler. FYI - the exception does not appear to actually break anything and the task completes successfully

[-----:~/code/kotlin-prototype] master(+24/-104)+ ± ./gradlew buildApplicationDockerImage
Failed to mark a promise as failure because it has succeeded already: DefaultChannelPromise@75b671cf(success)
java.util.NoSuchElementException: backend-response-forwarder
        at io.netty.channel.DefaultChannelPipeline.getContextOrDie(DefaultChannelPipeline.java:1073)
        at io.netty.channel.DefaultChannelPipeline.remove(DefaultChannelPipeline.java:423)
        at org.unbrokendome.awscodeartifact.mavenproxy.ProxyFrontendHandler.cleanupBackendChannel(ProxyFrontendHandler.kt:393)
        at org.unbrokendome.awscodeartifact.mavenproxy.ProxyFrontendHandler.cleanupAllState(ProxyFrontendHandler.kt:378)
        at org.unbrokendome.awscodeartifact.mavenproxy.ProxyFrontendHandler.afterResponseSent(ProxyFrontendHandler.kt:362)
        at org.unbrokendome.awscodeartifact.mavenproxy.ProxyFrontendHandler.write(ProxyFrontendHandler.kt:271)
        at io.netty.channel.AbstractChannelHandlerContext.invokeWrite0(AbstractChannelHandlerContext.java:717)
        at io.netty.channel.AbstractChannelHandlerContext.invokeWrite(AbstractChannelHandlerContext.java:709)
        at io.netty.channel.AbstractChannelHandlerContext$WriteTask.run(AbstractChannelHandlerContext.java:1069)
        at io.netty.util.concurrent.AbstractEventExecutor.safeExecute(AbstractEventExecutor.java:164)
        at io.netty.util.concurrent.SingleThreadEventExecutor.runAllTasks(SingleThreadEventExecutor.java:472)
        at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:500)
        at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:989)
        at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
        at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
        at java.base/java.lang.Thread.run(Thread.java:834)
<======-------> 50% CONFIGURING [6s]
> :migrations > Resolve files of :migrations:classpath

SSO credentials support

Theoretically, this can be added simply by adding the AWS sso maven artifact to the dependency list, but I can't test yet because AWS has been down the whole day, and it looks like SSO is almost literally the last thing to come back up. I'll create a PR for it as soon as I get a chance to test it.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.