Skip to content

Commit

Permalink
chore: update dependencies & gradle / add usePathStyle option (#2)
Browse files Browse the repository at this point in the history
* fix(ci): upgrade Gradle Build Action to v2.4.2 to prevent secret leakage

- Updated Gradle Build Action to v2.4.2 in GitHub workflows to fix potential secret leakage issue.

* chore: update dependencies

* chore: update gradle to 8.9

* fix: update task property annotations for Gradle 8 compatibility

- Change @input to @InputFile for RegularFileProperty types

* feat(plugin): Add usePathStyle option for S3 operations

Addresses breaking change in AWS SDK for Java S3 v2.18.0 that
affects S3-compatible storage systems. Introduces usePathStyle
configuration to maintain compatibility with MinIO in integration
tests and support specific S3 scenarios requiring path-style
addressing.

* fix(itest): update tests to force path style s3 access

- Enable usePathStyle in all integration test configurations
- Update Minio container to latest release (2024-08-03)
- Upgrade com.netflix.nebula.ospackage plugin to 11.9.1

* docs: add usePathStyle option to README

- added usePathStyle to README
- fixed wrong comment in DebPackage above usePathStyle

---------

Co-authored-by: Patrick Mirwald <mirwald@liftric.com>
  • Loading branch information
nvima and Patrick Mirwald authored Aug 12, 2024
1 parent 71992b9 commit e1d0373
Show file tree
Hide file tree
Showing 18 changed files with 67 additions and 38 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/pre-merge.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ jobs:
- name: Checkout
uses: actions/checkout@v3
- name: Cache
uses: gradle/gradle-build-action@v2
uses: gradle/gradle-build-action@v2.4.2
- name: Validate
run: ./gradlew check validatePlugins --continue
- name: Integration Test
Expand Down
2 changes: 1 addition & 1 deletion .github/workflows/publish-plugin.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ jobs:
- name: Checkout
uses: actions/checkout@v3
- name: Cache
uses: gradle/gradle-build-action@v2
uses: gradle/gradle-build-action@v2.4.2
- name: Validate
run: ./gradlew check validatePlugins --continue
- name: Integration Test
Expand Down
7 changes: 5 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ The `uploadPackage` task comes equipped with a range of both required and option
- **signingKeyPassphrase**: *(Required)* The passphrase for the PGP private key.
- **bucketPath**: *(Optional)* The path within the bucket to store the Apt Repository. If not specified, the repository is stored at the root of the bucket.
- **endpoint**: *(Optional)* Custom S3 endpoint. Use this to override the default AWS S3 endpoint.
- **usePathStyle**: *(Optional)* Boolean value indicating whether to use path-style access for S3 bucket operations. Default is false. Set to true when using S3-compatible storage systems like MinIO, or in specific scenarios with actual S3 where path-style access is required.
- **override**: *(Optional)* Boolean value indicating whether to override existing version of a Package. By default, it is `true`.

`Release File Attributes` can be override in s3AptRepository or per debPackage
Expand Down Expand Up @@ -73,7 +74,7 @@ In the `debPackage` section, you can specify package-specific attributes. These
- **packageArchitectures**: *(Required)* Set of architectures that the package supports.
- **packageName**, **packageVersion**: *(Optional)* These attributes can be used to override the default package name and version extracted form the Debian File.
- **origin**, **label**, **suite**, **component**, **architectures**, **codename**, **date**, **releaseDescription**, **releaseVersion**, **validUntil**, **notAutomatic**, **butAutomaticUpgrades**, **changelogs**, **snapshots** : *(Optional)* These attributes can be used to override the default Release file fields for the specific package.
- **accessKey**, **secretKey**, **bucket**, **bucketPath**, **region**, **endpoint**: *(Optional)* These attributes can be used to override their respective top-level attributes for the specific package.
- **accessKey**, **secretKey**, **bucket**, **bucketPath**, **region**, **endpoint**, **usePathStyle**: *(Optional)* These attributes can be used to override their respective top-level attributes for the specific package.



Expand All @@ -91,6 +92,7 @@ The `removePackage` task comes equipped with a range of both required and option
- **signingKeyPassphrase**: *(Required)* The passphrase for the PGP private key.
- **bucketPath**: *(Optional)* The path within the bucket to store the Apt Repository. If not specified, the repository is stored at the root of the bucket.
- **endpoint**: *(Optional)* Custom S3 endpoint. Use this to override the default AWS S3 endpoint.
- **usePathStyle**: *(Optional)* Boolean value indicating whether to use path-style access for S3 bucket operations. Default is false. Set to true when using S3-compatible storage systems like MinIO, or in specific scenarios with actual S3 where path-style access is required.
- **origin**: *(Optional)* The value of the 'Origin' field in the Release files. By default, it is 'Debian'.

`Release File Attributes` can be override in s3AptRepository or per debPackage
Expand All @@ -117,7 +119,7 @@ In the `debPackage` section, you can specify package-specific attributes. These
- **packageArchitectures**: *(Required)* Set of architectures that the package supports.
- **packageName**, **packageVersion**: *(Optional)* These attributes can be used to override the default package name and version extracted form the Debian File.
- **origin**, **label**, **suite**, **component**, **architectures**, **codename**, **date**, **releaseDescription**, **releaseVersion**, **validUntil**, **notAutomatic**, **butAutomaticUpgrades**, **changelogs**, **snapshots** : *(Optional)* These attributes can be used to override the default Release file fields for the specific package.
- **accessKey**, **secretKey**, **bucket**, **bucketPath**, **region**, **endpoint**: *(Optional)* These attributes can be used to override their respective top-level attributes for the specific package.
- **accessKey**, **secretKey**, **bucket**, **bucketPath**, **region**, **endpoint**, **usePathStyle**: *(Optional)* These attributes can be used to override their respective top-level attributes for the specific package.


### cleanPackages
Expand All @@ -130,6 +132,7 @@ The `cleanPackages` task comes equipped with a range of both required and option
- **secretKey**: *(Required)* The AWS Secret Key for accessing the S3 bucket. Can be overridden in the `debPackage` section.
- **bucketPath**: *(Optional)* The path within the bucket to store the Apt Repository. If not specified, the repository is stored at the root of the bucket.
- **endpoint**: *(Optional)* Custom S3 endpoint. Use this to override the default AWS S3 endpoint.
- **usePathStyle**: *(Optional)* Boolean value indicating whether to use path-style access for S3 bucket operations. Default is false. Set to true when using S3-compatible storage systems like MinIO, or in specific scenarios with actual S3 where path-style access is required.
- **suite**: *(Optional)* The value of the 'Suite' field in the Release files. By default, it is 'stable'.
- **component**: *(Optional)* The value of the 'Component' field in the Release files. By default, it is 'main'.

Expand Down
10 changes: 3 additions & 7 deletions build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -55,22 +55,18 @@ tasks {
gradlePlugin {
val integrationMain by sourceSets
testSourceSets(integrationMain)
website.set("https://github.com/Liftric/s3-apt-repository-plugin")
vcsUrl.set("https://github.com/Liftric/s3-apt-repository-plugin")
plugins {
create("s3-apt-repository-plugin") {
id = "$group.s3-apt-repository-plugin"
implementationClass = "$group.apt.S3AptRepositoryPlugin"
displayName = "s3-apt-repository-plugin"
tags.set(listOf("s3", "apt", "repository", "debian"))
}
}
}

pluginBundle {
website = "https://github.com/Liftric/s3-apt-repository-plugin"
vcsUrl = "https://github.com/Liftric/s3-apt-repository-plugin"
description = "A Gradle Plugin for managing an APT Repository on S3"
tags = listOf("s3", "apt", "repository", "debian")
}

dependencies {
implementation(libs.kotlinStdlibJdk8)
implementation(libs.apacheCommons)
Expand Down
2 changes: 1 addition & 1 deletion gradle/wrapper/gradle-wrapper.properties
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-7.4.2-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-8.9-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
29 changes: 14 additions & 15 deletions settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -4,31 +4,30 @@ pluginManagement {
dependencyResolutionManagement {
versionCatalogs {
create("libs") {
version("kotlin", "1.8.21")
version("ktor", "2.3.0")
version("junit", "5.9.3")
version("awsSdk", "2.17.125")
version("bouncycastle", "1.70")
version("testContainers", "1.18.3")
version("kotlin", "1.9.25")
version("junit", "5.10.3")
version("awsSdk", "2.27.0")
version("bouncycastle", "1.78.1")
version("testContainers", "1.20.1")

plugin("dockerCompose", "com.avast.gradle.docker-compose").version("0.16.12")
plugin("dockerCompose", "com.avast.gradle.docker-compose").version("0.17.7")
plugin("kotlinJvm", "org.jetbrains.kotlin.jvm").versionRef("kotlin")
plugin("kotlinSerialization", "org.jetbrains.kotlin.plugin.serialization").versionRef("kotlin")
plugin("gradlePluginPublish", "com.gradle.plugin-publish").version("1.2.0")
plugin("nemerosaVersioning", "net.nemerosa.versioning").version("3.0.0")
plugin("gradlePluginPublish", "com.gradle.plugin-publish").version("1.2.1")
plugin("nemerosaVersioning", "net.nemerosa.versioning").version("3.1.0")

library("kotlinStdlibJdk8", "org.jetbrains.kotlin", "kotlin-stdlib-jdk8").versionRef("kotlin")
library("junitBom", "org.junit", "junit-bom").versionRef("junit")
library("junitJupiter", "org.junit.jupiter", "junit-jupiter").versionRef("junit")
library("awsS3", "software.amazon.awssdk", "s3").versionRef("awsSdk")
library("bouncyCastleGPG", "org.bouncycastle", "bcpg-jdk15on").versionRef("bouncycastle")
library("bouncyCastleProvider", "org.bouncycastle", "bcprov-jdk15on").versionRef("bouncycastle")
library("xz", "org.tukaani", "xz").version("1.9")
library("apacheCommons", "org.apache.commons", "commons-compress").version("1.12")
library("bouncyCastleGPG", "org.bouncycastle", "bcpg-jdk18on").versionRef("bouncycastle")
library("bouncyCastleProvider", "org.bouncycastle", "bcprov-jdk18on").versionRef("bouncycastle")
library("xz", "org.tukaani", "xz").version("1.10")
library("apacheCommons", "org.apache.commons", "commons-compress").version("1.27.0")
library("testContainersJUnit5", "org.testcontainers", "junit-jupiter").versionRef("testContainers")
library("testContainersMain", "org.testcontainers", "testcontainers").versionRef("testContainers")
library("minio", "io.minio", "minio").version("8.5.3")
library("mockk", "io.mockk", "mockk").version("1.13.5")
library("minio", "io.minio", "minio").version("8.5.11")
library("mockk", "io.mockk", "mockk").version("1.13.12")
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ import com.netflix.gradle.plugins.deb.Deb
plugins {
id("com.liftric.s3-apt-repository-plugin")
id("com.netflix.nebula.ospackage") version "11.3.0"
id("com.netflix.nebula.ospackage") version "11.9.1"
}
group = "com.liftric.test"
Expand All @@ -84,6 +84,7 @@ s3AptRepository {
bucket.set("$CLEAN_PACKAGES_TEST_BUCKET")
region.set("eu-central-1")
endpoint.set("http://localhost:${MINIO_CONTAINER.getMappedPort(MINIO_PORT)}")
usePathStyle.set(true)
accessKey.set("$MINIO_ACCESS_KEY")
secretKey.set("$MINIO_SECRET_KEY")
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ abstract class ContainerBase {
val network: Network = Network.newNetwork()

val MINIO_CONTAINER: GenericContainer<*> =
GenericContainer(DockerImageName.parse("quay.io/minio/minio:RELEASE.2023-06-02T23-17-26Z"))
GenericContainer(DockerImageName.parse("quay.io/minio/minio:RELEASE.2024-08-03T04-33-23Z"))
.withPrivilegedMode(true)
.withNetwork(network)
.withNetworkAliases("minio")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,7 @@ import com.netflix.gradle.plugins.deb.Deb
plugins {
id("com.liftric.s3-apt-repository-plugin")
id("com.netflix.nebula.ospackage") version "11.3.0"
id("com.netflix.nebula.ospackage") version "11.9.1"
}
group = "com.liftric.test"
Expand Down Expand Up @@ -103,6 +103,7 @@ s3AptRepository {
bucket.set("$REMOVE_PACKAGE_TEST_BUCKET")
region.set("eu-central-1")
endpoint.set("http://localhost:${MINIO_CONTAINER.getMappedPort(MINIO_PORT)}")
usePathStyle.set(true)
accessKey.set("$MINIO_ACCESS_KEY")
secretKey.set("$MINIO_SECRET_KEY")
signingKeyPassphrase.set("$SIGNING_KEY_PASSPHRASE")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@ import com.netflix.gradle.plugins.deb.Deb
plugins {
id("com.liftric.s3-apt-repository-plugin")
id("com.netflix.nebula.ospackage") version "11.3.0"
id("com.netflix.nebula.ospackage") version "11.9.1"
}
group = "com.liftric.test"
Expand Down Expand Up @@ -100,6 +100,7 @@ s3AptRepository {
bucket.set("$UPLOAD_PACKAGE_TEST_BUCKET")
region.set("eu-central-1")
endpoint.set("http://localhost:${MINIO_CONTAINER.getMappedPort(MINIO_PORT)}")
usePathStyle.set(true)
accessKey.set("$MINIO_ACCESS_KEY")
secretKey.set("$MINIO_SECRET_KEY")
signingKeyPassphrase.set("$SIGNING_KEY_PASSPHRASE")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -59,7 +59,7 @@ import com.netflix.gradle.plugins.deb.Deb
plugins {
id("com.liftric.s3-apt-repository-plugin")
id("com.netflix.nebula.ospackage") version "11.3.0"
id("com.netflix.nebula.ospackage") version "11.9.1"
}
group = "com.liftric.test"
Expand Down Expand Up @@ -88,6 +88,7 @@ s3AptRepository {
bucket.set("$UPLOAD_PACKAGE_TEST_BUCKET_2")
region.set("eu-central-1")
endpoint.set("http://localhost:${MINIO_CONTAINER.getMappedPort(MINIO_PORT)}")
usePathStyle.set(true)
accessKey.set("$MINIO_ACCESS_KEY")
secretKey.set("$MINIO_SECRET_KEY")
signingKeyPassphrase.set("$SIGNING_KEY_PASSPHRASE")
Expand Down
3 changes: 3 additions & 0 deletions src/main/kotlin/com/liftric/apt/S3AptRepositoryPlugin.kt
Original file line number Diff line number Diff line change
Expand Up @@ -34,6 +34,7 @@ class S3AptRepositoryPlugin : Plugin<Project> {
task.bucketPath.set(extension.bucketPath.convention(""))
task.region.set(extension.region)
task.endpoint.set(extension.endpoint)
task.usePathStyle.set(extension.usePathStyle)
task.override.set(extension.override)
task.debianFiles.set(extension.debPackages)
task.signingKeyRingFile.set(extension.signingKeyRingFile)
Expand Down Expand Up @@ -63,6 +64,7 @@ class S3AptRepositoryPlugin : Plugin<Project> {
task.bucketPath.set(extension.bucketPath.convention(""))
task.region.set(extension.region)
task.endpoint.set(extension.endpoint)
task.usePathStyle.set(extension.usePathStyle)
task.debianFiles.set(extension.debPackages)
task.signingKeyRingFile.set(extension.signingKeyRingFile)
task.signingKeyPassphrase.set(extension.signingKeyPassphrase)
Expand Down Expand Up @@ -91,6 +93,7 @@ class S3AptRepositoryPlugin : Plugin<Project> {
task.bucketPath.set(extension.bucketPath.convention(""))
task.region.set(extension.region)
task.endpoint.set(extension.endpoint)
task.usePathStyle.set(extension.usePathStyle)
task.suite.set(extension.suite.convention(DEFAULT_SUITE))
task.components.set(extension.components.convention(DEFAULT_COMPONENT))
}
Expand Down
8 changes: 7 additions & 1 deletion src/main/kotlin/com/liftric/apt/extensions/DebPackage.kt
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,13 @@ import org.gradle.api.tasks.Input
import org.gradle.api.tasks.Internal
import org.gradle.api.tasks.Optional
import org.gradle.api.provider.Property
import org.gradle.api.tasks.InputFile

@Suppress("MemberVisibilityCanBePrivate")
@ConfigDsl
class DebPackage(@get:Internal val project: Project) {

@get:Input
@get:InputFile
// The Package file to upload. Currently only Debian Files are supported */
val file: RegularFileProperty = project.objects.fileProperty()

Expand All @@ -36,6 +37,11 @@ class DebPackage(@get:Internal val project: Project) {
// Used for override the default S3 endpoint
val endpoint: Property<String?> = project.objects.property(String::class.java)

@get:Input
@get:Optional
// Used to force s3 path style access
val usePathStyle: Property<Boolean?> = project.objects.property(Boolean::class.java)

@get:Input
@get:Optional
// Optional: Used for override the default accessKey
Expand Down
1 change: 1 addition & 0 deletions src/main/kotlin/com/liftric/apt/extensions/extension.kt
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ abstract class S3AptRepositoryPluginExtension(val project: Project) {
abstract val bucketPath: Property<String>
abstract val region: Property<String>
abstract val endpoint: Property<String>
abstract val usePathStyle: Property<Boolean>

/** Override Versions that already exist in Apt Repository, Default is true */
abstract val override: Property<Boolean>
Expand Down
4 changes: 3 additions & 1 deletion src/main/kotlin/com/liftric/apt/service/AwsS3Client.kt
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ class AwsS3Client(
accessKey: String,
secretKey: String,
region: String,
endpoint: String? = null,
endpoint: String?,
usePathStyle: Boolean,
) {
private val s3Client by lazy {
with(S3Client.builder()) {
Expand All @@ -39,6 +40,7 @@ class AwsS3Client(
endpointOverride(URI.create(endpoint))
}
}
forcePathStyle(usePathStyle)
region(convertToRegion(region))
credentialsProvider(
StaticCredentialsProvider.create(
Expand Down
7 changes: 6 additions & 1 deletion src/main/kotlin/com/liftric/apt/tasks/CleanPackages.kt
Original file line number Diff line number Diff line change
Expand Up @@ -36,6 +36,10 @@ abstract class CleanPackages : DefaultTask() {
@get:Optional
abstract val endpoint: Property<String>

@get:Input
@get:Optional
abstract val usePathStyle: Property<Boolean>

@TaskAction
fun main() {
val suiteValue = suite.get()
Expand All @@ -46,8 +50,9 @@ abstract class CleanPackages : DefaultTask() {
val bucketPathValue = bucketPath.get()
val regionValue = region.get()
val endpointValue = endpoint.orNull
val usePathStyleValue = usePathStyle.getOrElse(false)

val s3Client = AwsS3Client(accessKeyValue, secretKeyValue, regionValue, endpointValue)
val s3Client = AwsS3Client(accessKeyValue, secretKeyValue, regionValue, endpointValue, usePathStyleValue)

val usedPackages = getUsedPackagesPoolKeys(s3Client, bucketValue, bucketPathValue, suiteValue, componentValue)
cleanPackages(logger, s3Client, bucketValue, bucketPathValue, componentValue, usedPackages)
Expand Down
7 changes: 6 additions & 1 deletion src/main/kotlin/com/liftric/apt/tasks/RemovePackage.kt
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ abstract class RemovePackage : DefaultTask() {

@get:Input
@get:Optional
abstract val usePathStyle: Property<Boolean>

@get:InputFile
@get:Optional
abstract val signingKeyRingFile: RegularFileProperty

@get:Input
Expand Down Expand Up @@ -124,6 +128,7 @@ abstract class RemovePackage : DefaultTask() {
val bucketPath = debianFile.bucketPath.orNull ?: bucketPath.get()
val region = debianFile.region.orNull ?: region.get()
val endpoint = debianFile.endpoint.orNull ?: endpoint.orNull
val usePathStyle = debianFile.usePathStyle.orNull ?: usePathStyle.orNull ?: false

/** Release file values **/
val origin = debianFile.origin.orNull ?: origin.get()
Expand All @@ -141,7 +146,7 @@ abstract class RemovePackage : DefaultTask() {
val changelogs = debianFile.changelogs.orNull ?: changelogs.orNull
val snapshots = debianFile.snapshots.orNull ?: snapshots.orNull

val s3Client = AwsS3Client(accessKey, secretKey, region, endpoint)
val s3Client = AwsS3Client(accessKey, secretKey, region, endpoint, usePathStyle)
val debianPackages =
PackagesFactory.parseDebianFile(inputFile, archs, "", packageName, packageVersion)

Expand Down
9 changes: 7 additions & 2 deletions src/main/kotlin/com/liftric/apt/tasks/UploadPackage.kt
Original file line number Diff line number Diff line change
Expand Up @@ -40,10 +40,14 @@ abstract class UploadPackage : DefaultTask() {

@get:Input
@get:Optional
abstract val override: Property<Boolean>
abstract val usePathStyle: Property<Boolean>

@get:Input
@get:Optional
abstract val override: Property<Boolean>

@get:InputFile
@get:Optional
abstract val signingKeyRingFile: RegularFileProperty

@get:Input
Expand Down Expand Up @@ -126,6 +130,7 @@ abstract class UploadPackage : DefaultTask() {
val secretKey = debianFile.secretKey.orNull ?: secretKey.get()
val region = debianFile.region.orNull ?: region.get()
val endpoint = debianFile.endpoint.orNull ?: endpoint.orNull
val usePathStyle = debianFile.usePathStyle.orNull ?: usePathStyle.orNull ?: false
val bucket = debianFile.bucket.orNull ?: bucket.get()
val bucketPath = debianFile.bucketPath.orNull ?: bucketPath.get()

Expand All @@ -145,7 +150,7 @@ abstract class UploadPackage : DefaultTask() {
val changelogs = debianFile.changelogs.orNull ?: changelogs.orNull
val snapshots = debianFile.snapshots.orNull ?: snapshots.orNull

val s3Client = AwsS3Client(accessKey, secretKey, region, endpoint)
val s3Client = AwsS3Client(accessKey, secretKey, region, endpoint, usePathStyle)
val debianPoolBucketKey = getPoolBucketKey(inputFile.name, components)
val debianPackages = PackagesFactory.parseDebianFile(
inputFile, packageArchitectures, debianPoolBucketKey, packageName, packageVersion
Expand Down

0 comments on commit e1d0373

Please sign in to comment.