├── files └── default-binarystore.xml ├── manifests ├── service.pp ├── install.pp ├── user.pp ├── repo.pp ├── db.pp ├── init.pp └── config.pp ├── .msync.yml ├── .rubocop.yml ├── .github ├── labeler.yml ├── workflows │ ├── labeler.yml │ ├── ci.yml │ ├── release.yml │ └── prepare_release.yml ├── PULL_REQUEST_TEMPLATE.md ├── ISSUE_TEMPLATE.md └── release.yml ├── .puppet-lint.rc ├── lib └── puppet │ └── type │ ├── artifactory_access_setting.rb │ ├── artifactory_access_settings.rb │ └── artifactory_yaml_file.rb ├── .editorconfig ├── spec ├── classes │ └── init_spec.rb └── spec_helper.rb ├── .fixtures.yml ├── .gitignore ├── .pmtignore ├── CHANGELOG.md ├── Gemfile ├── metadata.json ├── Rakefile ├── .overcommit.yml ├── REFERENCE.md ├── LICENSE └── README.md /files/default-binarystore.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /manifests/service.pp: -------------------------------------------------------------------------------- 1 | # @api private 2 | class artifactory::service { 3 | service { 'artifactory': 4 | ensure => running, 5 | enable => true, 6 | } 7 | } 8 | -------------------------------------------------------------------------------- /.msync.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Managed by modulesync - DO NOT EDIT 3 | # https://voxpupuli.org/docs/updating-files-managed-with-modulesync/ 4 | 5 | modulesync_config_version: '10.4.0' 6 | -------------------------------------------------------------------------------- /.rubocop.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Managed by modulesync - DO NOT EDIT 3 | # https://voxpupuli.org/docs/updating-files-managed-with-modulesync/ 4 | 5 | inherit_gem: 6 | voxpupuli-test: rubocop.yml 7 | -------------------------------------------------------------------------------- /.github/labeler.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Managed by modulesync - DO NOT EDIT 3 | # https://voxpupuli.org/docs/updating-files-managed-with-modulesync/ 4 | 5 | skip-changelog: 6 | - head-branch: ['^release-*', 'release'] 7 | -------------------------------------------------------------------------------- /.puppet-lint.rc: -------------------------------------------------------------------------------- 1 | # Managed by modulesync - DO NOT EDIT 2 | # https://voxpupuli.org/docs/updating-files-managed-with-modulesync/ 3 | 4 | --fail-on-warnings 5 | --no-parameter_documentation-check 6 | --no-parameter_types-check 7 | -------------------------------------------------------------------------------- /manifests/install.pp: -------------------------------------------------------------------------------- 1 | # @api private 2 | class artifactory::install ( 3 | String[1] $package_name = $artifactory::package_name, 4 | String[1] $package_version = $artifactory::package_version, 5 | ) { 6 | package { $package_name: 7 | ensure => $package_version, 8 | } 9 | } 10 | -------------------------------------------------------------------------------- /lib/puppet/type/artifactory_access_setting.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | Puppet::Type.newtype(:artifactory_access_setting) do 4 | newparam(:name, namevar: true) do 5 | desc 'Name of setting in dotted notation.' 6 | end 7 | 8 | newparam(:value) do 9 | desc 'The value of the setting' 10 | end 11 | end 12 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | # editorconfig.org 2 | 3 | # Managed by modulesync - DO NOT EDIT 4 | # https://voxpupuli.org/docs/updating-files-managed-with-modulesync/ 5 | 6 | root = true 7 | 8 | [*] 9 | charset = utf-8 10 | end_of_line = lf 11 | indent_size = 2 12 | tab_width = 2 13 | indent_style = space 14 | insert_final_newline = true 15 | trim_trailing_whitespace = true 16 | -------------------------------------------------------------------------------- /spec/classes/init_spec.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'spec_helper' 4 | 5 | describe 'artifactory' do 6 | context 'supported operating systems' do 7 | on_supported_os.each do |os, facts| 8 | context "on #{os}" do 9 | let(:facts) { facts } 10 | 11 | it { is_expected.to compile.with_all_deps } 12 | end 13 | end 14 | end 15 | end 16 | -------------------------------------------------------------------------------- /manifests/user.pp: -------------------------------------------------------------------------------- 1 | # @api private 2 | class artifactory::user ( 3 | Integer $uid = $artifactory::uid, 4 | Integer $gid = $artifactory::gid, 5 | ) { 6 | group { 'artifactory': 7 | gid => $gid, 8 | } 9 | 10 | user { 'artifactory': 11 | uid => $uid, 12 | gid => $gid, 13 | home => '/var/opt/jfrog/artifactory', 14 | managehome => false, 15 | shell => '/sbin/nologin', 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /.fixtures.yml: -------------------------------------------------------------------------------- 1 | --- 2 | fixtures: 3 | repositories: 4 | stdlib: https://github.com/puppetlabs/puppetlabs-stdlib 5 | concat: https://github.com/puppetlabs/puppetlabs-concat 6 | extlib: https://github.com/voxpupuli/puppet-extlib 7 | systemd: https://github.com/voxpupuli/puppet-systemd 8 | yumrepo_core: https://github.com/puppetlabs/puppetlabs-yumrepo_core 9 | postgresql: https://github.com/puppetlabs/puppetlabs-postgresql 10 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Managed by modulesync - DO NOT EDIT 2 | # https://voxpupuli.org/docs/updating-files-managed-with-modulesync/ 3 | 4 | /pkg/ 5 | /Gemfile.lock 6 | /Gemfile.local 7 | /vendor/ 8 | /.vendor/ 9 | /spec/fixtures/manifests/ 10 | /spec/fixtures/modules/ 11 | /.vagrant/ 12 | /.bundle/ 13 | /.ruby-version 14 | /coverage/ 15 | /log/ 16 | /.idea/ 17 | /.dependencies/ 18 | /.librarian/ 19 | /Puppetfile.lock 20 | *.iml 21 | .*.sw? 22 | /.yardoc/ 23 | /Guardfile 24 | bolt-debug.log 25 | .rerun.json 26 | -------------------------------------------------------------------------------- /.github/workflows/labeler.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Managed by modulesync - DO NOT EDIT 3 | # https://voxpupuli.org/docs/updating-files-managed-with-modulesync/ 4 | 5 | name: "Pull Request Labeler" 6 | 7 | # yamllint disable-line rule:truthy 8 | on: 9 | pull_request_target: {} 10 | 11 | permissions: 12 | contents: read 13 | pull-requests: write 14 | 15 | jobs: 16 | labeler: 17 | permissions: 18 | contents: read 19 | pull-requests: write 20 | runs-on: ubuntu-latest 21 | steps: 22 | - uses: actions/labeler@v5 23 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Managed by modulesync - DO NOT EDIT 3 | # https://voxpupuli.org/docs/updating-files-managed-with-modulesync/ 4 | 5 | name: CI 6 | 7 | # yamllint disable-line rule:truthy 8 | on: 9 | pull_request: {} 10 | push: 11 | branches: 12 | - main 13 | - master 14 | 15 | concurrency: 16 | group: ${{ github.ref_name }} 17 | cancel-in-progress: true 18 | 19 | permissions: 20 | contents: read 21 | 22 | jobs: 23 | puppet: 24 | name: Puppet 25 | uses: voxpupuli/gha-puppet/.github/workflows/basic.yml@v4 26 | -------------------------------------------------------------------------------- /manifests/repo.pp: -------------------------------------------------------------------------------- 1 | # @api private 2 | class artifactory::repo ( 3 | $edition = $artifactory::edition, 4 | ) { 5 | $baseurl = $edition ? { 6 | 'pro' => 'https://releases.jfrog.io/artifactory/artifactory-pro-rpms/', 7 | default => 'https://releases.jfrog.io/artifactory/artifactory-rpms/', 8 | } 9 | 10 | yumrepo { 'Artifactory': 11 | enabled => true, 12 | baseurl => $baseurl, 13 | descr => 'Artifactory', 14 | repo_gpgcheck => true, 15 | gpgcheck => false, 16 | gpgkey => "${baseurl}/repodata/repomd.xml.key", 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /.github/PULL_REQUEST_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 9 | #### Pull Request (PR) description 10 | 13 | 14 | #### This Pull Request (PR) fixes the following issues 15 | 21 | -------------------------------------------------------------------------------- /.pmtignore: -------------------------------------------------------------------------------- 1 | # Managed by modulesync - DO NOT EDIT 2 | # https://voxpupuli.org/docs/updating-files-managed-with-modulesync/ 3 | 4 | /docs/ 5 | /pkg/ 6 | /Gemfile 7 | /Gemfile.lock 8 | /Gemfile.local 9 | /vendor/ 10 | /.vendor/ 11 | /spec/ 12 | /Rakefile 13 | /.vagrant/ 14 | /.bundle/ 15 | /.ruby-version 16 | /coverage/ 17 | /log/ 18 | /.idea/ 19 | /.dependencies/ 20 | /.github/ 21 | /.librarian/ 22 | /Puppetfile.lock 23 | /Puppetfile 24 | *.iml 25 | /.editorconfig 26 | /.fixtures.yml 27 | /.gitignore 28 | /.msync.yml 29 | /.overcommit.yml 30 | /.pmtignore 31 | /.rspec 32 | /.rspec_parallel 33 | /.rubocop.yml 34 | /.sync.yml 35 | .*.sw? 36 | /.yardoc/ 37 | /.yardopts 38 | /Dockerfile 39 | /HISTORY.md 40 | -------------------------------------------------------------------------------- /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Managed by modulesync - DO NOT EDIT 3 | # https://voxpupuli.org/docs/updating-files-managed-with-modulesync/ 4 | 5 | name: Release 6 | 7 | # yamllint disable-line rule:truthy 8 | on: 9 | push: 10 | tags: 11 | - '*' 12 | 13 | permissions: 14 | contents: write 15 | 16 | jobs: 17 | release: 18 | name: Release 19 | uses: voxpupuli/gha-puppet/.github/workflows/release.yml@v3 20 | with: 21 | allowed_owner: 'voxpupuli' 22 | secrets: 23 | # Configure secrets here: 24 | # https://docs.github.com/en/actions/security-guides/encrypted-secrets 25 | username: ${{ secrets.PUPPET_FORGE_USERNAME }} 26 | api_key: ${{ secrets.PUPPET_FORGE_API_KEY }} 27 | -------------------------------------------------------------------------------- /.github/ISSUE_TEMPLATE.md: -------------------------------------------------------------------------------- 1 | 10 | 11 | ## Affected Puppet, Ruby, OS and module versions/distributions 12 | 13 | - Puppet: 14 | - Ruby: 15 | - Distribution: 16 | - Module version: 17 | 18 | ## How to reproduce (e.g Puppet code you use) 19 | 20 | ## What are you seeing 21 | 22 | ## What behaviour did you expect instead 23 | 24 | ## Output log 25 | 26 | ## Any additional information you'd like to impart 27 | -------------------------------------------------------------------------------- /CHANGELOG.md: -------------------------------------------------------------------------------- 1 | # Changelog 2 | 3 | All notable changes to this project will be documented in this file. 4 | Each new release typically also includes the latest modulesync defaults. 5 | These should not affect the functionality of the module. 6 | 7 | ## [v1.0.0](https://github.com/voxpupuli/puppet-artifactory/tree/v1.0.0) (2025-11-13) 8 | 9 | [Full Changelog](https://github.com/voxpupuli/puppet-artifactory/compare/4a6d878e885983f28d96a1156e1a86a2ceac7e1f...v1.0.0) 10 | 11 | **Merged pull requests:** 12 | 13 | - Add README.md badges [\#2](https://github.com/voxpupuli/puppet-artifactory/pull/2) ([alexjfisher](https://github.com/alexjfisher)) 14 | 15 | 16 | 17 | \* *This Changelog was automatically generated by [github_changelog_generator](https://github.com/github-changelog-generator/github-changelog-generator)* 18 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | # Managed by modulesync - DO NOT EDIT 2 | # https://voxpupuli.org/docs/updating-files-managed-with-modulesync/ 3 | 4 | source ENV['GEM_SOURCE'] || 'https://rubygems.org' 5 | 6 | group :test do 7 | gem 'voxpupuli-test', '~> 13.0', :require => false 8 | gem 'puppet_metadata', '~> 5.0', :require => false 9 | end 10 | 11 | group :development do 12 | gem 'guard-rake', :require => false 13 | gem 'overcommit', '>= 0.39.1', :require => false 14 | end 15 | 16 | group :system_tests do 17 | gem 'voxpupuli-acceptance', '~> 4.0', :require => false 18 | end 19 | 20 | group :release do 21 | gem 'voxpupuli-release', '~> 5.0', :require => false 22 | end 23 | 24 | gem 'rake', :require => false 25 | 26 | gem 'openvox', ENV.fetch('OPENVOX_GEM_VERSION', [">= 7", "< 9"]), :require => false, :groups => [:test] 27 | 28 | # vim: syntax=ruby 29 | -------------------------------------------------------------------------------- /spec/spec_helper.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | # Managed by modulesync - DO NOT EDIT 4 | # https://voxpupuli.org/docs/updating-files-managed-with-modulesync/ 5 | 6 | # puppetlabs_spec_helper will set up coverage if the env variable is set. 7 | # We want to do this if lib exists and it hasn't been explicitly set. 8 | ENV['COVERAGE'] ||= 'yes' if Dir.exist?(File.expand_path('../lib', __dir__)) 9 | 10 | require 'voxpupuli/test/spec_helper' 11 | 12 | RSpec.configure do |c| 13 | c.facterdb_string_keys = false 14 | end 15 | 16 | add_mocked_facts! 17 | 18 | if File.exist?(File.join(__dir__, 'default_module_facts.yml')) 19 | facts = YAML.safe_load(File.read(File.join(__dir__, 'default_module_facts.yml'))) 20 | facts&.each do |name, value| 21 | add_custom_fact name.to_sym, value 22 | end 23 | end 24 | Dir['./spec/support/spec/**/*.rb'].sort.each { |f| require f } 25 | -------------------------------------------------------------------------------- /.github/workflows/prepare_release.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Managed by modulesync - DO NOT EDIT 3 | # https://voxpupuli.org/docs/updating-files-managed-with-modulesync/ 4 | 5 | name: 'Prepare Release' 6 | 7 | on: 8 | workflow_dispatch: 9 | inputs: 10 | version: 11 | description: 'Module version to be released. Must be a valid semver string without leading v. (1.2.3)' 12 | required: false 13 | 14 | permissions: 15 | contents: write 16 | pull-requests: write 17 | 18 | jobs: 19 | release_prep: 20 | uses: 'voxpupuli/gha-puppet/.github/workflows/prepare_release.yml@v3' 21 | with: 22 | version: ${{ github.event.inputs.version }} 23 | allowed_owner: 'voxpupuli' 24 | secrets: 25 | # Configure secrets here: 26 | # https://docs.github.com/en/actions/security-guides/encrypted-secrets 27 | github_pat: '${{ secrets.PCCI_PAT_RELEASE_PREP }}' 28 | -------------------------------------------------------------------------------- /metadata.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "puppet-artifactory", 3 | "version": "1.0.1-rc0", 4 | "author": "Vox Pupuli", 5 | "summary": "Puppet Artifactory module", 6 | "license": "Apache-2.0", 7 | "source": "https://github.com/voxpupuli/puppet-artifactory", 8 | "project_page": "https://github.com/voxpupuli/puppet-artifactory", 9 | "issues_url": "https://github.com/voxpupuli/puppet-artifactory/issues", 10 | "dependencies": [ 11 | { 12 | "name": "puppet/extlib", 13 | "version_requirement": ">= 6.0.0 < 8.0.0" 14 | }, 15 | { 16 | "name": "puppetlabs/stdlib", 17 | "version_requirement": ">= 9.0.0 < 10.0.0" 18 | } 19 | ], 20 | "operatingsystem_support": [ 21 | { 22 | "operatingsystem": "RedHat", 23 | "operatingsystemrelease": [ 24 | "8" 25 | ] 26 | } 27 | ], 28 | "requirements": [ 29 | { 30 | "name": "openvox", 31 | "version_requirement": ">= 8.19.0 < 9.0.0" 32 | } 33 | ] 34 | } 35 | -------------------------------------------------------------------------------- /.github/release.yml: -------------------------------------------------------------------------------- 1 | --- 2 | # Managed by modulesync - DO NOT EDIT 3 | # https://voxpupuli.org/docs/updating-files-managed-with-modulesync/ 4 | 5 | # https://docs.github.com/en/repositories/releasing-projects-on-github/automatically-generated-release-notes 6 | 7 | changelog: 8 | exclude: 9 | labels: 10 | - duplicate 11 | - invalid 12 | - modulesync 13 | - question 14 | - skip-changelog 15 | - wont-fix 16 | - wontfix 17 | 18 | categories: 19 | - title: Breaking Changes 🛠 20 | labels: 21 | - backwards-incompatible 22 | 23 | - title: New Features 🎉 24 | labels: 25 | - enhancement 26 | 27 | - title: Bug Fixes 🐛 28 | labels: 29 | - bug 30 | 31 | - title: Documentation Updates 📚 32 | labels: 33 | - documentation 34 | - docs 35 | 36 | - title: Dependency Updates ⬆️ 37 | labels: 38 | - dependencies 39 | 40 | - title: Other Changes 41 | labels: 42 | - "*" 43 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | # Managed by modulesync - DO NOT EDIT 2 | # https://voxpupuli.org/docs/updating-files-managed-with-modulesync/ 3 | 4 | begin 5 | require 'voxpupuli/test/rake' 6 | rescue LoadError 7 | # only available if gem group test is installed 8 | end 9 | 10 | begin 11 | require 'voxpupuli/acceptance/rake' 12 | rescue LoadError 13 | # only available if gem group acceptance is installed 14 | end 15 | 16 | begin 17 | require 'voxpupuli/release/rake_tasks' 18 | rescue LoadError 19 | # only available if gem group releases is installed 20 | else 21 | GCGConfig.user = 'voxpupuli' 22 | GCGConfig.project = 'puppet-artifactory' 23 | end 24 | 25 | desc "Run main 'test' task and report merged results to coveralls" 26 | task test_with_coveralls: [:test] do 27 | if Dir.exist?(File.expand_path('../lib', __FILE__)) 28 | require 'coveralls/rake/task' 29 | Coveralls::RakeTask.new 30 | Rake::Task['coveralls:push'].invoke 31 | else 32 | puts 'Skipping reporting to coveralls. Module has no lib dir' 33 | end 34 | end 35 | 36 | # vim: syntax=ruby 37 | -------------------------------------------------------------------------------- /manifests/db.pp: -------------------------------------------------------------------------------- 1 | # @api private 2 | class artifactory::db ( 3 | String[1] $db_name = $artifactory::db_name, 4 | Stdlib::Port $db_port = $artifactory::db_port, 5 | String[1] $db_user = $artifactory::db_user, 6 | Variant[ 7 | Sensitive[String[1]], 8 | String[1] 9 | ] $db_password = $artifactory::db_password, 10 | ) { 11 | # We only 'include' the main postgresql server class here 12 | # If any customisation is needed, it should be done in the user's profile code before declaring the artifactory class 13 | include postgresql::server 14 | 15 | # We can one small bit of sanity checking though... 16 | unless $postgresql::server::port == $db_port { 17 | fail("PostgreSQL is configured to listen on ${postgresql::server::port}. This does not match ${db_port}. Please declare `postgresql::server` yourself before including the artifactory module") 18 | } 19 | 20 | postgresql::server::db { $db_name: 21 | user => $db_name, 22 | owner => $db_name, 23 | password => postgresql::postgresql_password($db_name, $db_password), 24 | } 25 | } 26 | -------------------------------------------------------------------------------- /.overcommit.yml: -------------------------------------------------------------------------------- 1 | # Managed by modulesync - DO NOT EDIT 2 | # https://voxpupuli.org/docs/updating-files-managed-with-modulesync/ 3 | # 4 | # Hooks are only enabled if you take action. 5 | # 6 | # To enable the hooks run: 7 | # 8 | # ``` 9 | # bundle exec overcommit --install 10 | # # ensure .overcommit.yml does not harm to you and then 11 | # bundle exec overcommit --sign 12 | # ``` 13 | # 14 | # (it will manage the .git/hooks directory): 15 | # 16 | # Examples howto skip a test for a commit or push: 17 | # 18 | # ``` 19 | # SKIP=RuboCop git commit 20 | # SKIP=PuppetLint git commit 21 | # SKIP=RakeTask git push 22 | # ``` 23 | # 24 | # Don't invoke overcommit at all: 25 | # 26 | # ``` 27 | # OVERCOMMIT_DISABLE=1 git commit 28 | # ``` 29 | # 30 | # Read more about overcommit: https://github.com/brigade/overcommit 31 | # 32 | # To manage this config yourself in your module add 33 | # 34 | # ``` 35 | # .overcommit.yml: 36 | # unmanaged: true 37 | # ``` 38 | # 39 | # to your modules .sync.yml config 40 | --- 41 | PreCommit: 42 | RuboCop: 43 | enabled: true 44 | description: 'Runs rubocop on modified files only' 45 | command: ['bundle', 'exec', 'rubocop'] 46 | RakeTarget: 47 | enabled: true 48 | description: 'Runs lint on modified files only' 49 | targets: 50 | - 'lint' 51 | command: ['bundle', 'exec', 'rake'] 52 | YamlSyntax: 53 | enabled: true 54 | JsonSyntax: 55 | enabled: true 56 | TrailingWhitespace: 57 | enabled: true 58 | 59 | PrePush: 60 | RakeTarget: 61 | enabled: true 62 | description: 'Run rake targets' 63 | targets: 64 | - 'validate' 65 | - 'test' 66 | - 'rubocop' 67 | command: ['bundle', 'exec', 'rake'] 68 | -------------------------------------------------------------------------------- /lib/puppet/type/artifactory_access_settings.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'yaml' 4 | 5 | Puppet::Type.newtype(:artifactory_access_settings) do 6 | @doc = <<-DOC 7 | @summary 8 | Generates a access.config.patch.yml file as needed using configuration values from `artifactory_access_setting` resources. 9 | @api private 10 | DOC 11 | 12 | newparam(:path, namevar: true) do 13 | desc <<-DOC 14 | The access configuration directory. 15 | 16 | This is the directory where the existing config is expected to be found, as well as where any generated patch file will be created. 17 | DOC 18 | end 19 | 20 | autorequire(:file) do 21 | [patch_file_path] 22 | end 23 | 24 | newparam(:owner, parent: Puppet::Type::File::Owner) do 25 | desc <<-DOC 26 | Specifies the owner of the access.config.patch.yml file. 27 | DOC 28 | 29 | defaultto 'artifactory' 30 | end 31 | 32 | newparam(:group, parent: Puppet::Type::File::Group) do 33 | desc <<-DOC 34 | Specifies a permissions group of the access.config.patch.yml file. 35 | gid. 36 | DOC 37 | 38 | defaultto 'artifactory' 39 | end 40 | 41 | def patch_file_path 42 | "#{self[:path]}/access.config.patch.yml" 43 | end 44 | 45 | def access_settings 46 | @access_settings ||= catalog.resources.select { |resource| resource.is_a?(Puppet::Type.type(:artifactory_access_setting)) } 47 | end 48 | 49 | def values_to_set 50 | values = access_settings.each_with_object({}) do |res, memo| 51 | memo[res[:name]] = res[:value] if config_patch_needed?(res[:name], res[:value]) 52 | end 53 | 54 | debug "values to set #{values}" 55 | values 56 | end 57 | 58 | def current_config 59 | @current_config ||= begin 60 | YAML.load_file("#{self[:path]}/access.config.latest.yml") 61 | rescue Errno::ENOENT 62 | info 'access.config.latest.yml not found. Treating as empty hash.' 63 | {} 64 | rescue StandardError => e 65 | warning "Error reading #{self[:path]}/access.config.latest.yml #{e.inspect}" 66 | # Should we raise here instead?? 67 | {} 68 | end 69 | end 70 | 71 | def config_patch_needed?(setting, expected) 72 | path = setting.split('.') 73 | 74 | begin 75 | actual = current_config.dig(*path) 76 | rescue StandardError => e 77 | # We can't for example dig into `True` values 78 | warning e.inspect 79 | return true 80 | end 81 | 82 | # Artifactory seems to import Integers values and convert them to Strings. 83 | # If we're expecting an Integer and the config file has a String, we need to try to coerce it to an Integer before comparing 84 | expected != (if expected.is_a?(Integer) && actual.is_a?(String) 85 | begin 86 | Integer(actual) 87 | rescue StandardError 88 | actual 89 | end 90 | else 91 | actual 92 | end) 93 | end 94 | 95 | def expand_dotted_paths(settings) 96 | settings.each_with_object({}) do |(key, value), result| 97 | *path, leaf = key.split('.') 98 | path.reduce(result) { |acc, elem| acc[elem] ||= {} }[leaf] = value 99 | end 100 | end 101 | 102 | def should_content 103 | @should_content ||= begin 104 | content = expand_dotted_paths(values_to_set) 105 | if content == {} 106 | nil 107 | else 108 | content.to_yaml 109 | end 110 | end 111 | end 112 | 113 | def generate 114 | file_opts = { 115 | ensure: :file, 116 | path: patch_file_path, 117 | owner: self[:owner], 118 | group: self[:group], 119 | mode: '0640', 120 | } 121 | 122 | [Puppet::Type.type(:file).new(file_opts)] 123 | end 124 | 125 | def eval_generate 126 | file = catalog.resource("File[#{patch_file_path}]") 127 | 128 | if (content = should_content) 129 | file[:content] = content 130 | else 131 | file[:ensure] = :absent 132 | end 133 | 134 | [file] 135 | end 136 | end 137 | -------------------------------------------------------------------------------- /manifests/init.pp: -------------------------------------------------------------------------------- 1 | # @summary Installs and configures Artifactory 2 | # 3 | # @param manage_repo 4 | # Whether to manage the artifactory yum repository 5 | # @param edition 6 | # Controls which version of Artifactory is installed 7 | # @param package_name 8 | # The Artifactory package name 9 | # @param package_version 10 | # The RPM version of the Artifactory package, (or `latest`, `installed` etc.) 11 | # @param db_type 12 | # The database type. Artifactory works with other databases, but strongly recommends only using `postgresql` 13 | # @param db_host 14 | # The host of database server housing Artifactory's database 15 | # @param db_name 16 | # The name of the database (or SERVICE for `oracle` databases) 17 | # @param db_user 18 | # The username used to connect to the database 19 | # @param db_port 20 | # The TCP port the database listens on 21 | # @param db_password 22 | # The password of the `db_user`. By default a random password will be generated, and cached on your puppet server. Only use when you have a single Puppetserver 23 | # @param db_url 24 | # Instead of allowing this Puppet module to set the JDBC database URL based on, `db_type`, `db_host`, `db_port` and `db_name`, manaully override the URL by setting this parameter 25 | # @param additional_system_config 26 | # A hash of any additional configuration. This will be merged into the default configuration, and database configuration when building the `system.yaml` file. 27 | # @param manage_db 28 | # Whether to install and configure Artifactory's database. Only supported for `db_type` postgresql 29 | # @param uid 30 | # If set, the UID to use when managing the `artifactory` user. If not set, the module will not manage the user 31 | # @param gid 32 | # The GID to use for the `artifactory` group when managing the `artifactory` user. Will default to the same as the `uid` 33 | # @param master_key 34 | # If set, this will be used at the value for the `master.key`. This should not be changed after Artifactory has been deployed. 35 | # @param binary_store_config_xml 36 | # The contents to be used for a custom binary-store.xml file. When not set, the default file-system configuration will be used. 37 | # @param jvm_max_heap_size 38 | # The Java Maximum Heap Size. Used in the `-Xmx` java option. 39 | # @param jvm_min_heap_size 40 | # The Java Minimum Heap Size. Used in the '-Xms' java option. Defaults to the `jvm_max_heap_size`. 41 | # @param jvm_extra_args 42 | # Any extra java options. For example, setting the stack size with `-Xss1m` 43 | # @param system_properties 44 | # A hash of Artifactory 'system properties'. These will be added to the `artifactory.system.properties` file. Set a value to `undef` if you want to remove it from the file. 45 | class artifactory ( 46 | Boolean $manage_repo = true, 47 | Enum['oss','pro'] $edition = 'oss', 48 | String[1] $package_name = "jfrog-artifactory-${edition}", 49 | String[1] $package_version = 'installed', 50 | 51 | Enum[ 52 | 'derby', 53 | 'mariadb', 54 | 'mssql', 55 | 'mysql', 56 | 'oracle', 57 | 'postgresql' 58 | ] $db_type = 'postgresql', 59 | Boolean $manage_db = true, 60 | Stdlib::Host $db_host = 'localhost', 61 | String[1] $db_name = 'artifactory', 62 | String[1] $db_user = 'artifactory', 63 | Stdlib::Port $db_port = 5432, 64 | Variant[ 65 | Sensitive[String[1]], 66 | String[1] 67 | ] $db_password = extlib::cache_data('artifactory', 'db_password', extlib::random_password(16)), 68 | Optional[String[1]] $db_url = undef, 69 | 70 | Hash $additional_system_config = {}, 71 | Optional[Integer] $uid = undef, 72 | Optional[Integer] $gid = $uid, 73 | 74 | Optional[ 75 | Variant[ 76 | Sensitive[Pattern[/\A(\h{32}|\h{64})\z/]], 77 | Pattern[/\A(\h{32}|\h{64})\z/] 78 | ] 79 | ] $master_key = undef, 80 | 81 | Optional[String[1]] $binary_store_config_xml = undef, 82 | 83 | String[1] $jvm_max_heap_size = '2G', 84 | String[1] $jvm_min_heap_size = $jvm_max_heap_size, 85 | Array[String[1]] $jvm_extra_args = [], 86 | 87 | Hash $system_properties = {}, 88 | ) { 89 | if $manage_repo { 90 | contain artifactory::repo 91 | Class['artifactory::repo'] -> Class['artifactory::install'] 92 | } 93 | 94 | if $manage_db { 95 | unless $db_type == 'postgresql' { fail('Only postgresql is supported when `manage_db` is `true`') } 96 | contain artifactory::db 97 | Class['artifactory::db'] -> Class['artifactory::service'] 98 | } 99 | 100 | if $uid and $gid { 101 | contain artifactory::user 102 | Class['artifactory::user'] -> Class['artifactory::install'] 103 | } 104 | 105 | contain artifactory::install 106 | contain artifactory::config 107 | contain artifactory::service 108 | 109 | Class['artifactory::install'] 110 | -> Class['artifactory::config'] 111 | ~> Class['artifactory::service'] 112 | } 113 | -------------------------------------------------------------------------------- /manifests/config.pp: -------------------------------------------------------------------------------- 1 | # @api private 2 | class artifactory::config ( 3 | Enum['derby', 'mariadb', 'mssql', 'mysql', 'oracle', 'postgresql'] $db_type = 'postgresql', 4 | Stdlib::Host $db_host = $artifactory::db_host, 5 | String[1] $db_name = $artifactory::db_name, 6 | String[1] $db_user = $artifactory::db_user, 7 | Stdlib::Port $db_port = $artifactory::db_port, 8 | Variant[ 9 | Sensitive[String[1]], 10 | String[1] 11 | ] $db_password = $artifactory::db_password, 12 | Optional[String[1]] $db_url = $artifactory::db_url, 13 | Hash $additional_system_config = $artifactory::additional_system_config, 14 | Optional[String[1]] $binary_store_config_xml = $artifactory::binary_store_config_xml, 15 | 16 | Variant[ 17 | Undef, 18 | Sensitive[Pattern[/\A(\h{32}|\h{64})\z/]], 19 | Pattern[/\A(\h{32}|\h{64})\z/] 20 | ] $master_key = $artifactory::master_key, 21 | 22 | String[1] $jvm_max_heap_size = $artifactory::jvm_max_heap_size, 23 | String[1] $jvm_min_heap_size = $artifactory::jvm_min_heap_size, 24 | Array[String[1]] $jvm_extra_args = $artifactory::jvm_extra_args, 25 | 26 | Hash $system_properties = $artifactory::system_properties 27 | ) { 28 | $jfrog_home = '/opt/jfrog' 29 | $datadir = "${jfrog_home}/artifactory/var" 30 | 31 | $base_config = { 32 | 'configVersion' => 1, 33 | 'shared' => { 34 | 'security' => undef, 35 | 'node' => undef, 36 | 'database' => {}, 37 | 'user' => 'artifactory', 38 | }, 39 | 'access' => undef, 40 | } 41 | 42 | if $db_url { 43 | $_db_url = $db_url 44 | } else { 45 | $_db_url = $db_type ? { 46 | 'postgresql' => "jdbc:postgresql://${db_host}:${db_port}/${db_name}", 47 | /(mariadb|mysql)/ => "jdbc:${db_type}://${db_host}:${db_port}/${db_name}?characterEncoding=UTF-8&elideSetAutoCommits=true&useSSL=false", 48 | 'mssql' => "jdbc:sqlserver://${db_host}:${db_port};databaseName=${db_name};sendStringParametersAsUnicode=false;applicationName=Artifactory Binary Repository", 49 | 'oracle' => "jdbc:oracle:thin:@//[${db_host}][${db_port}]/${db_name}", 50 | } 51 | } 52 | 53 | $db_driver = $db_type ? { 54 | 'postgresql' => 'org.postgresql.Driver', 55 | 'mariadb' => 'org.mariadb.jdbc.Driver', 56 | 'mysql' => 'com.mysql.jdbc.Driver', 57 | 'mssql' => 'com.microsoft.sqlserver.jdbc.SQLServerDriver', 58 | 'oracle' => 'oracle.jdbc.OracleDriver', 59 | } 60 | 61 | if $db_type == 'postgresql' { 62 | $allow_non_postgresql = false 63 | } else { 64 | $allow_non_postgresql = true 65 | } 66 | 67 | if $db_type == 'derby' { 68 | $db_config = { 69 | 'allowNonPostgresql' => $allow_non_postgresql, 70 | } 71 | } else { 72 | $db_config = { 73 | 'allowNonPostgresql' => $allow_non_postgresql, 74 | 'type' => $db_type, 75 | 'driver' => $db_driver, 76 | 'url' => $_db_url, 77 | 'username' => $db_user, 78 | 'password' => $db_password, 79 | } 80 | } 81 | 82 | $extra_java_opts = ([ 83 | "-Xms${jvm_min_heap_size}", 84 | "-Xmx${jvm_max_heap_size}", 85 | ] + $jvm_extra_args).unique.join(' ') 86 | 87 | $master_key_file = "${datadir}/etc/security/master.key" 88 | 89 | if $master_key { 90 | file { "${datadir}/etc/security": 91 | ensure => directory, 92 | owner => 'artifactory', 93 | group => 'artifactory', 94 | mode => '0640', 95 | } 96 | 97 | file { $master_key_file: 98 | ensure => file, 99 | owner => 'artifactory', 100 | group => 'artifactory', 101 | mode => '0640', 102 | content => Sensitive($master_key), 103 | } 104 | 105 | $key = $master_key 106 | } else { 107 | $key = $master_key_file 108 | } 109 | 110 | artifactory_yaml_file { "${datadir}/etc/system.yaml": 111 | ensure => present, 112 | config => Sensitive($base_config.deep_merge( 113 | { 'shared' => { 'database' => $db_config, 'extraJavaOpts' => $extra_java_opts } }, 114 | $additional_system_config 115 | )), 116 | owner => 'artifactory', 117 | group => 'artifactory', 118 | mode => '0640', 119 | key => $key, 120 | } 121 | 122 | if $binary_store_config_xml { 123 | $binary_store_content = $binary_store_config_xml 124 | } else { 125 | $binary_store_content = file('artifactory/default-binarystore.xml') 126 | } 127 | 128 | file { "${datadir}/etc/artifactory/binarystore.xml": 129 | ensure => file, 130 | owner => 'artifactory', 131 | group => 'artifactory', 132 | mode => '0640', 133 | content => $binary_store_content, 134 | } 135 | 136 | $changes = $system_properties.map |$key, $value| { 137 | if $value == undef { 138 | "rm \"${key}\"" 139 | } else { 140 | "set \"${key}\" \"${value}\"" 141 | } 142 | } 143 | 144 | unless $changes.empty { 145 | augeas { 'artifactory.system.properties': 146 | context => "/files${datadir}/etc/artifactory/artifactory.system.properties", 147 | incl => "${datadir}/etc/artifactory/artifactory.system.properties", 148 | lens => 'Properties.lns', 149 | changes => $changes, 150 | } 151 | } 152 | 153 | artifactory_access_settings { "${datadir}/etc/access": } 154 | } 155 | -------------------------------------------------------------------------------- /lib/puppet/type/artifactory_yaml_file.rb: -------------------------------------------------------------------------------- 1 | # frozen_string_literal: true 2 | 3 | require 'openssl' 4 | require 'base64' 5 | require 'yaml' 6 | 7 | require 'puppet/type/file/owner' 8 | require 'puppet/type/file/group' 9 | require 'puppet/type/file/mode' 10 | 11 | Puppet::Type.newtype(:artifactory_yaml_file) do 12 | @doc = <<-DOC 13 | @summary 14 | Used to generates the system.yaml file but replaces its content only if encrypted fields don't decrypt to strings matching the plaintext versions from `content` 15 | @api private 16 | DOC 17 | 18 | attr_accessor :replace_file_content 19 | 20 | ensurable do 21 | defaultvalues 22 | 23 | defaultto { :present } 24 | end 25 | 26 | def exists? 27 | self[:ensure] == :present 28 | end 29 | 30 | newparam(:path, namevar: true) do 31 | validate do |value| 32 | raise ArgumentError, 'File paths must be fully qualified' unless Puppet::Util.absolute_path?(value, :posix) 33 | end 34 | end 35 | 36 | newparam(:owner, parent: Puppet::Type::File::Owner) do 37 | desc <<-DOC 38 | Specifies the owner of the destination file. Valid options: a string containing a username or integer containing a uid. 39 | DOC 40 | end 41 | 42 | newparam(:group, parent: Puppet::Type::File::Group) do 43 | desc <<-DOC 44 | Specifies a permissions group for the destination file. Valid options: a string containing a group name or integer containing a 45 | gid. 46 | DOC 47 | end 48 | 49 | newparam(:mode, parent: Puppet::Type::File::Mode) do 50 | desc <<-DOC 51 | Specifies the permissions mode of the destination file. Valid options: a string containing a permission mode value in octal notation. 52 | DOC 53 | end 54 | 55 | newparam(:show_diff, boolean: true, parent: Puppet::Parameter::Boolean) do 56 | desc <<-DOC 57 | Specifies whether to set the show_diff parameter for the file resource. Useful for hiding secrets stored in hiera from insecure 58 | reporting methods. 59 | DOC 60 | end 61 | 62 | newparam(:key) do 63 | validate do |value| 64 | raise ArgumentError, 'key must be an absolute path to a key file, or the raw hex key string' unless Puppet::Util.absolute_path?(value, :posix) || value.chomp =~ %r{\A(\h{32}|\h{64})\z} 65 | end 66 | 67 | munge do |value| 68 | if Puppet::Util.absolute_path?(value, :posix) 69 | if File.exist?(value) 70 | File.read(value).chomp 71 | else 72 | debug "#{value} doesn't exist" 73 | nil 74 | end 75 | else 76 | value.chomp 77 | end 78 | end 79 | end 80 | 81 | newparam(:config) do 82 | munge do |value| 83 | current = retrieve 84 | target = YAML.dump(deep_unwrap(value)) 85 | 86 | if current.nil? || resource[:key].nil? 87 | resource.replace_file_content = true 88 | target 89 | else 90 | decrypted_content = deep_transform_strings(YAML.safe_load(current), %r{\A\h{6}\.aesgcm(128|256)\.[A-Za-z0-9_-]+\z}) { |s| decrypt_string(s, resource[:key]) } 91 | if decrypted_content == deep_unwrap(value) 92 | debug 'decrypted_content matches target state' 93 | current 94 | else 95 | debug 'decrypted_content DID NOT match target state' 96 | resource.replace_file_content = true 97 | target 98 | end 99 | end 100 | end 101 | 102 | def retrieve 103 | if File.exist?(resource.parameter(:path).value) 104 | File.read(resource.parameter(:path).value) 105 | else 106 | debug "file doesn't exist yet" 107 | nil 108 | end 109 | end 110 | 111 | def deep_transform_strings(obj, regex, &transform) 112 | case obj 113 | when Hash 114 | obj.transform_values { |v| deep_transform_strings(v, regex, &transform) } 115 | when Array 116 | obj.map { |e| deep_transform_strings(e, regex, &transform) } 117 | when String 118 | regex.match?(obj) ? transform.call(obj) : obj 119 | else 120 | obj 121 | end 122 | end 123 | 124 | def deep_unwrap(obj) 125 | if obj.is_a?(Puppet::Pops::Types::PSensitiveType::Sensitive) 126 | resource.parameter(:config).sensitive = true 127 | obj = obj.unwrap 128 | end 129 | 130 | case obj 131 | when Hash 132 | obj.transform_values { |v| deep_unwrap(v) } 133 | when Array 134 | obj.map { |v| deep_unwrap(v) } 135 | else 136 | obj 137 | end 138 | end 139 | 140 | def decrypt_string(string, master_key_hex) 141 | _label, alg, payload_b64 = string.split('.', 3) 142 | key = [master_key_hex].pack('H*') 143 | 144 | if alg == 'aesgcm256' 145 | expected_key_bytesize = 32 146 | cipher = 'aes-256-gcm' 147 | else 148 | expected_key_bytesize = 16 149 | cipher = 'aes-128-gcm' 150 | end 151 | 152 | if key.bytesize != expected_key_bytesize 153 | warning 'master key size did not match size used to encrypt data' 154 | return string 155 | end 156 | 157 | begin 158 | buf = Base64.urlsafe_decode64(payload_b64) 159 | 160 | iv = buf[0, 12] 161 | ct = buf[12...-16] 162 | tag = buf[-16, 16] 163 | 164 | c = OpenSSL::Cipher.new(cipher) 165 | c.decrypt 166 | c.key = key 167 | c.iv = iv 168 | c.auth_tag = tag 169 | c.update(ct) + c.final 170 | rescue StandardError => e 171 | warning "Error decrypting string in Artifactory yaml: #{e.inspect}" 172 | string 173 | end 174 | end 175 | end 176 | 177 | autorequire(:file) do 178 | [self[:path]] 179 | end 180 | 181 | def generate 182 | file_opts = { 183 | ensure: self[:ensure] == :absent ? :absent : :file 184 | } 185 | 186 | %i[ 187 | path 188 | owner 189 | group 190 | mode 191 | show_diff 192 | ].each do |param| 193 | file_opts[param] = self[param] unless self[param].nil? 194 | end 195 | 196 | excluded_metaparams = %i[before notify require subscribe tag] 197 | 198 | Puppet::Type.metaparams.each do |metaparam| 199 | file_opts[metaparam] = self[metaparam] unless self[metaparam].nil? || excluded_metaparams.include?(metaparam) 200 | end 201 | 202 | [Puppet::Type.type(:file).new(file_opts)] 203 | end 204 | 205 | def eval_generate 206 | if replace_file_content 207 | catalog.resource("File[#{self[:path]}]")[:content] = self[:config] 208 | catalog.resource("File[#{self[:path]}]").parameter(:content).sensitive = true if parameter(:config).sensitive 209 | end 210 | [catalog.resource("File[#{self[:path]}]")] 211 | end 212 | 213 | def set_sensitive_parameters(sensitive_parameters) # rubocop:disable Naming/AccessorMethodName 214 | if sensitive_parameters.include?(:config) 215 | sensitive_parameters.delete(:config) 216 | parameter(:config).sensitive = true 217 | end 218 | 219 | if sensitive_parameters.include?(:key) 220 | sensitive_parameters.delete(:key) 221 | parameter(:key).sensitive = true 222 | end 223 | 224 | super(sensitive_parameters) 225 | end 226 | end 227 | -------------------------------------------------------------------------------- /REFERENCE.md: -------------------------------------------------------------------------------- 1 | # Reference 2 | 3 | 4 | 5 | ## Table of Contents 6 | 7 | ### Classes 8 | 9 | #### Public Classes 10 | 11 | * [`artifactory`](#artifactory): Installs and configures Artifactory 12 | 13 | #### Private Classes 14 | 15 | * `artifactory::config` 16 | * `artifactory::db` 17 | * `artifactory::install` 18 | * `artifactory::repo` 19 | * `artifactory::service` 20 | * `artifactory::user` 21 | 22 | ### Resource types 23 | 24 | #### Public Resource types 25 | 26 | * [`artifactory_access_setting`](#artifactory_access_setting): Name of setting in dotted notation. 27 | 28 | #### Private Resource types 29 | 30 | * `artifactory_access_settings`: Generates a access.config.patch.yml file as needed using configuration values from `artifactory_access_setting` resources. 31 | * `artifactory_yaml_file`: Used to generates the system.yaml file but replaces its content only if encrypted fields don't decrypt to strings matching the plaintext versions from `content` 32 | 33 | ## Classes 34 | 35 | ### `artifactory` 36 | 37 | Installs and configures Artifactory 38 | 39 | #### Parameters 40 | 41 | The following parameters are available in the `artifactory` class: 42 | 43 | * [`manage_repo`](#-artifactory--manage_repo) 44 | * [`edition`](#-artifactory--edition) 45 | * [`package_name`](#-artifactory--package_name) 46 | * [`package_version`](#-artifactory--package_version) 47 | * [`db_type`](#-artifactory--db_type) 48 | * [`db_host`](#-artifactory--db_host) 49 | * [`db_name`](#-artifactory--db_name) 50 | * [`db_user`](#-artifactory--db_user) 51 | * [`db_port`](#-artifactory--db_port) 52 | * [`db_password`](#-artifactory--db_password) 53 | * [`db_url`](#-artifactory--db_url) 54 | * [`additional_system_config`](#-artifactory--additional_system_config) 55 | * [`manage_db`](#-artifactory--manage_db) 56 | * [`uid`](#-artifactory--uid) 57 | * [`gid`](#-artifactory--gid) 58 | * [`master_key`](#-artifactory--master_key) 59 | * [`binary_store_config_xml`](#-artifactory--binary_store_config_xml) 60 | * [`jvm_max_heap_size`](#-artifactory--jvm_max_heap_size) 61 | * [`jvm_min_heap_size`](#-artifactory--jvm_min_heap_size) 62 | * [`jvm_extra_args`](#-artifactory--jvm_extra_args) 63 | * [`system_properties`](#-artifactory--system_properties) 64 | 65 | ##### `manage_repo` 66 | 67 | Data type: `Boolean` 68 | 69 | Whether to manage the artifactory yum repository 70 | 71 | Default value: `true` 72 | 73 | ##### `edition` 74 | 75 | Data type: `Enum['oss','pro']` 76 | 77 | Controls which version of Artifactory is installed 78 | 79 | Default value: `'oss'` 80 | 81 | ##### `package_name` 82 | 83 | Data type: `String[1]` 84 | 85 | The Artifactory package name 86 | 87 | Default value: `"jfrog-artifactory-${edition}"` 88 | 89 | ##### `package_version` 90 | 91 | Data type: `String[1]` 92 | 93 | The RPM version of the Artifactory package, (or `latest`, `installed` etc.) 94 | 95 | Default value: `'installed'` 96 | 97 | ##### `db_type` 98 | 99 | Data type: 100 | 101 | ```puppet 102 | Enum[ 103 | 'derby', 104 | 'mariadb', 105 | 'mssql', 106 | 'mysql', 107 | 'oracle', 108 | 'postgresql' 109 | ] 110 | ``` 111 | 112 | The database type. Artifactory works with other databases, but strongly recommends only using `postgresql` 113 | 114 | Default value: `'postgresql'` 115 | 116 | ##### `db_host` 117 | 118 | Data type: `Stdlib::Host` 119 | 120 | The host of database server housing Artifactory's database 121 | 122 | Default value: `'localhost'` 123 | 124 | ##### `db_name` 125 | 126 | Data type: `String[1]` 127 | 128 | The name of the database (or SERVICE for `oracle` databases) 129 | 130 | Default value: `'artifactory'` 131 | 132 | ##### `db_user` 133 | 134 | Data type: `String[1]` 135 | 136 | The username used to connect to the database 137 | 138 | Default value: `'artifactory'` 139 | 140 | ##### `db_port` 141 | 142 | Data type: `Stdlib::Port` 143 | 144 | The TCP port the database listens on 145 | 146 | Default value: `5432` 147 | 148 | ##### `db_password` 149 | 150 | Data type: 151 | 152 | ```puppet 153 | Variant[ 154 | Sensitive[String[1]], 155 | String[1] 156 | ] 157 | ``` 158 | 159 | The password of the `db_user`. By default a random password will be generated, and cached on your puppet server. Only use when you have a single Puppetserver 160 | 161 | Default value: `extlib::cache_data('artifactory', 'db_password', extlib::random_password(16))` 162 | 163 | ##### `db_url` 164 | 165 | Data type: `Optional[String[1]]` 166 | 167 | Instead of allowing this Puppet module to set the JDBC database URL based on, `db_type`, `db_host`, `db_port` and `db_name`, manaully override the URL by setting this parameter 168 | 169 | Default value: `undef` 170 | 171 | ##### `additional_system_config` 172 | 173 | Data type: `Hash` 174 | 175 | A hash of any additional configuration. This will be merged into the default configuration, and database configuration when building the `system.yaml` file. 176 | 177 | Default value: `{}` 178 | 179 | ##### `manage_db` 180 | 181 | Data type: `Boolean` 182 | 183 | Whether to install and configure Artifactory's database. Only supported for `db_type` postgresql 184 | 185 | Default value: `true` 186 | 187 | ##### `uid` 188 | 189 | Data type: `Optional[Integer]` 190 | 191 | If set, the UID to use when managing the `artifactory` user. If not set, the module will not manage the user 192 | 193 | Default value: `undef` 194 | 195 | ##### `gid` 196 | 197 | Data type: `Optional[Integer]` 198 | 199 | The GID to use for the `artifactory` group when managing the `artifactory` user. Will default to the same as the `uid` 200 | 201 | Default value: `$uid` 202 | 203 | ##### `master_key` 204 | 205 | Data type: 206 | 207 | ```puppet 208 | Optional[ 209 | Variant[ 210 | Sensitive[Pattern[/\A(\h{32}|\h{64})\z/]], 211 | Pattern[/\A(\h{32}|\h{64})\z/] 212 | ] 213 | ] 214 | ``` 215 | 216 | If set, this will be used at the value for the `master.key`. This should not be changed after Artifactory has been deployed. 217 | 218 | Default value: `undef` 219 | 220 | ##### `binary_store_config_xml` 221 | 222 | Data type: `Optional[String[1]]` 223 | 224 | The contents to be used for a custom binary-store.xml file. When not set, the default file-system configuration will be used. 225 | 226 | Default value: `undef` 227 | 228 | ##### `jvm_max_heap_size` 229 | 230 | Data type: `String[1]` 231 | 232 | The Java Maximum Heap Size. Used in the `-Xmx` java option. 233 | 234 | Default value: `'2G'` 235 | 236 | ##### `jvm_min_heap_size` 237 | 238 | Data type: `String[1]` 239 | 240 | The Java Minimum Heap Size. Used in the '-Xms' java option. Defaults to the `jvm_max_heap_size`. 241 | 242 | Default value: `$jvm_max_heap_size` 243 | 244 | ##### `jvm_extra_args` 245 | 246 | Data type: `Array[String[1]]` 247 | 248 | Any extra java options. For example, setting the stack size with `-Xss1m` 249 | 250 | Default value: `[]` 251 | 252 | ##### `system_properties` 253 | 254 | Data type: `Hash` 255 | 256 | A hash of Artifactory 'system properties'. These will be added to the `artifactory.system.properties` file. Set a value to `undef` if you want to remove it from the file. 257 | 258 | Default value: `{}` 259 | 260 | ## Resource types 261 | 262 | ### `artifactory_access_setting` 263 | 264 | Name of setting in dotted notation. 265 | 266 | #### Parameters 267 | 268 | The following parameters are available in the `artifactory_access_setting` type. 269 | 270 | * [`name`](#-artifactory_access_setting--name) 271 | * [`value`](#-artifactory_access_setting--value) 272 | 273 | ##### `name` 274 | 275 | namevar 276 | 277 | Name of setting in dotted notation. 278 | 279 | ##### `value` 280 | 281 | The value of the setting 282 | 283 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | 203 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # puppet/artifactory 2 | 3 | [![Build Status](https://github.com/voxpupuli/puppet-artifactory/workflows/CI/badge.svg)](https://github.com/voxpupuli/puppet-artifactory/actions?query=workflow%3ACI) 4 | [![Release](https://github.com/voxpupuli/puppet-artifactory/actions/workflows/release.yml/badge.svg)](https://github.com/voxpupuli/puppet-artifactory/actions/workflows/release.yml) 5 | [![Puppet Forge](https://img.shields.io/puppetforge/v/puppet/artifactory.svg)](https://forge.puppetlabs.com/puppet/artifactory) 6 | [![Puppet Forge - downloads](https://img.shields.io/puppetforge/dt/puppet/artifactory.svg)](https://forge.puppetlabs.com/puppet/artifactory) 7 | [![Puppet Forge - endorsement](https://img.shields.io/puppetforge/e/puppet/artifactory.svg)](https://forge.puppetlabs.com/puppet/artifactory) 8 | [![Puppet Forge - scores](https://img.shields.io/puppetforge/f/puppet/artifactory.svg)](https://forge.puppetlabs.com/puppet/artifactory) 9 | [![puppetmodule.info docs](http://www.puppetmodule.info/images/badge.png)](http://www.puppetmodule.info/m/puppet-artifactory) 10 | [![Apache-2 License](https://img.shields.io/github/license/voxpupuli/puppet-artifactory.svg)](LICENSE) 11 | 12 | ## Table of Contents 13 | 14 | 1. [Description](#description) 15 | 1. [Setup - The basics of getting started with artifactory](#setup) 16 | * [What artifactory affects](#what-artifactory-affects) 17 | * [Setup requirements](#setup-requirements) 18 | * [Beginning with artifactory](#beginning-with-artifactory) 19 | 1. [Usage - Configuration options and additional functionality](#usage) 20 | 1. [Reference - An under-the-hood peek at what the module is doing and how](#reference) 21 | 1. [Limitations - OS compatibility, etc.](#limitations) 22 | 1. [Development - Guide for contributing to the module](#development) 23 | 24 | ## Description 25 | 26 | This module manages the installation of Artifactory, (OSS or commercial editions). 27 | 28 | It has been developed for and tested with Artifactory 7 on RHEL 8, but should also function on later versions of RHEL (and its clones). 29 | 30 | ## Setup 31 | 32 | ### What artifactory affects 33 | 34 | The module installs Artifactory 7 from RPM packages. 35 | It manages Artifactory's `system.yaml` configuration file, the `master.key` file, `binarystore.xml` and settings within the `artifactory.system.properties` file. 36 | 37 | It has been developed for use with `PostgreSQL` as Artifactory's backend database and will, by default, manage the creation of the database instance too. 38 | 39 | ### Setup Requirements 40 | 41 | When `manage_db` is `true`, (the default), `puppetlabs/postgresql` will be used to configure the database instance. 42 | It is still recommended that before declaring the `artifactory` module, you include your own `postgresql` profile to tune and customise the PostgreSQL installation. 43 | 44 | Artifactory 7 includes its own Java distribution and JDBC drivers, such that you shouldn't need to include any puppet code to manage these. 45 | 46 | ### Beginning with artifactory 47 | 48 | The module has a single public class. At its simplest, and assuming your server has Internet access and is able to reach JFrog's public yum servers, you can simply include the base class to get a working installation. 49 | 50 | ```puppet 51 | include artifactory 52 | ``` 53 | 54 | All defaults will be used. This will include a default installation of postgreSQL to host Artifactory's database. 55 | In practice, there are several customisations you will probably want to make. 56 | 57 | #### Controlling which version is installed 58 | 59 | The `edition` parameter defaults to `oss`. It can be set to `pro` to install the commercial edition of Artifactory. The setting influences the repository configured when `manage_repo` is set to `true`, as well as the default for the `package_name` parameter. 60 | 61 | The `package_version` parameter can be used to specify an exact package version, (the RPM version), of Artifactory to install. 62 | 63 | If you set `manage_repo` to `false`, the module will not configure the yum repository, but will still expect the appropriate package to be available. 64 | 65 | #### PostgreSQL 66 | 67 | When `manage_db` is `true`, the `artifactory::db` class will be included to ensure PostgreSQL is installed by using the `puppetlabs/postgresql` module. 68 | 69 | The code will `include postgresql::globals`, but in order to customise the PostgreSQL installation you will want to declare this with your own options *before* including artifactory. 70 | 71 | Detailed instructions on how to customise PostgreSQL with the `puppetlabs/postgresl` module are outside of the scope for this document, but as a very simple example you could use PostgreSQL 16 with 2 GB configured for the important `shared_buffers` setting. 72 | 73 | ```puppet 74 | class { 'postgresql::globals': 75 | encoding => 'utf8', 76 | locale => 'en_US.utf8', 77 | version => '16', 78 | manage_dnf_module => true, 79 | } 80 | 81 | postgresql::server::config_entry { 'shared_buffers': 82 | value => '2048MB', 83 | } 84 | 85 | class { 'artifactory': 86 | db_password => Sensitive($some_secret_db_password), # Specify the db password instead of letting the module generate and cache its own. 87 | } 88 | ``` 89 | 90 | #### Using a different database 91 | 92 | JFrog *strongly* recommend using PostgreSQL. This module should allow you to use one of the other supported databases too, but there has been very limited testing, and `manage_db` must be set to `false`. 93 | 94 | ```puppet 95 | class { 'artifactory': 96 | manage_db => false, 97 | db_type => 'mariadb', 98 | db_port => '3306', 99 | db_host => 'my-mariadb.example.com', 100 | db_password => Sensitive($some_secret_db_password), 101 | } 102 | ``` 103 | 104 | (You can of course also use an external PostgreSQL by setting `manage_db` to `false` and specifying `db_host` parameters etc.) 105 | 106 | #### Customising the JDBC database URL 107 | 108 | The module will automatically set a JDBC database URL in `system.yaml` with a format based on the `db_type`. If you need to use a custom URL, (perhaps to set some advanced JDBC driver properties), you can use the `db_url` parameter. 109 | 110 | #### JVM Memory and other settings 111 | 112 | By default, the module will configure the Java process heap size to be 2GB. This can be customised by using the `jvm_max_heap_size` parameter (and `jvm_min_heap_size` if you don't want the minimum to be the same as the maximum value). Other JVM options can be configured using the `jvm_extra_args` parameter. 113 | 114 | In this example, the heap size is set to 8GB, and JMX based monitoring has been configured on the `localhost` interface. 115 | 116 | ```puppet 117 | class { 'artifactory': 118 | jvm_max_heap_size => '8G', 119 | jvm_extra_args => { 120 | '-Dcom.sun.management.jmxremote', 121 | '-Dcom.sun.management.jmxremote.port=9000', 122 | '-Dcom.sun.management.jmxremote.local.only=true', 123 | '-Dcom.sun.management.jmxremote.authenticate=false', 124 | '-Dcom.sun.management.jmxremote.ssl=false', 125 | }, 126 | } 127 | ``` 128 | 129 | #### The Binary Store configuration 130 | 131 | By default, the module will configure the `binarystore.xml` file with the very basic default local filesystem configuration. 132 | If you need something more complicated, (for example because you're storing artifacts in AWS S3), you must pass the complete `binarystore.xml` content as a string in the `binary_store_config_xml` parameter. 133 | 134 | #### Custom `system.yaml` configuration 135 | 136 | The various database related parameters and the `jvm` parameters influence the contents of `system.yaml`. If you need to override any of this configuration file, you can use the `additional_system_config` parameter. 137 | This hash will be merged to form the final `system.yaml` configuration. It can be used to overwrite _any_ of the configuration including any of that related to the database configuration, (for example if you needed to specify the name of a custom JDBC driver). 138 | 139 | In this example, it is being used to change the listen address of various Artifactory services. (Note, configuring a reverse proxy is outside the scope of this module). 140 | 141 | ```puppet 142 | class { 'artifactory': 143 | additional_system_config => { 144 | 'router' => { 145 | 'entrypoints' => { 146 | 'externalHost' => '127.0.0.1', 147 | }, 148 | }, 149 | 'artifactory' => { 150 | 'tomcat' => { 151 | 'connector' => { 152 | 'extraConfig' => 'address="127.0.0.1"', 153 | }, 154 | }, 155 | }, 156 | }, 157 | } 158 | ``` 159 | 160 | #### Management of the `artifactory` group and user 161 | 162 | If you need to manage the `artifactory` user's UID and GID, then use the `uid` and (optionally `gid`) parameters. When not set, the user and group will simply be created by the RPM's post install script. 163 | 164 | #### Customising System Properties 165 | 166 | On some occasions, you might need to configure a setting in `artifactory.system.properties`. You can use the `system_properties` parameter for this. Augeas will be used to either set or remove a property from this file. 167 | 168 | For example, to remove an old, no longer used setting, use `undef` as its value. 169 | 170 | ```puppet 171 | class { 'artifactory': 172 | system_properties => { 173 | 'artifactory.gems.compact.index.enabled' => undef, # Remove this old setting that isn't needed/wanted in modern Artifactory 7. 174 | }, 175 | } 176 | ``` 177 | 178 | #### The `master.key` 179 | 180 | Artifactory uses the `master.key` to encrypt secrets in the database and importantly to also encrypt plaintext secrets it finds in `system.yaml`, especially the database password. 181 | 182 | You can set the `master_key` parameter to specify your own 128 or 256 bit AES key, (as a 32 or 64 character hex string). If you don't use your own key, Artifactory will generate one when it first starts. Updating the key is *not* supported. 183 | 184 | This module is clever enough to not replace the encrypted values Artifactory generates in the `system.yaml` with the original plaintext passwords on each puppet run. 185 | 186 | #### Support for Sensitive and Deferred secrets 187 | 188 | Both the `master_key` and `db_password` parameters will correctly accept `Sensitive` values and automatically redact them from logs etc. 189 | `Deferred` values are also supported by _this_ module, but unfortunately, if `manage_db` is set to `true`, `db_password` currently doesn't work if `Deferred` due to a bug in the `puppetlabs/postgresql` module. 190 | 191 | #### Access Configuration 192 | 193 | The `artifactory_access_setting` type can be used to configure [access](https://jfrog.com/help/r/jfrog-installation-setup-documentation/access-yaml-configuration) settings. 194 | 195 | The name of each resource should be the configuration setting in dotted notation. Set the `value` parameter to the required value. 196 | 197 | For example, enforcing two of the security related settings. 198 | 199 | ```puppet 200 | artifactory_access_setting { 'security.password-policy.length': 201 | value => 8, 202 | } 203 | 204 | artifactory_access_setting { 'security.authentication.ldap.referral-strategy': 205 | value => 'ignore', 206 | } 207 | ``` 208 | 209 | ## Reference 210 | 211 | [Puppet Strings REFERENCE.md](REFERENCE.md) 212 | 213 | ## Limitations 214 | 215 | * Tested on CentOS 8 216 | * Puppet/Openvox 7 or greater. 217 | * Artifactory 7 only. This module won't manage upgrading from version 6 for you. 218 | * Not all configuration files can currently be managed. For example, content of the `access.config.latest.yml` configuration file. 219 | * This module doesn't manage the contents of Artifactory. It can not be used to create repositories, configure authentication sources, manage permissions etc. 220 | 221 | ## Development 222 | 223 | This module is maintained by [Vox Pupuli](https://voxpupuli.org/). 224 | 225 | It was written by [Alex Fisher](https://github.com/alexjfisher) and is licensed under the Apache-2.0 License. 226 | --------------------------------------------------------------------------------