entitlements-gitrepo-auditor-plugin

This commit is contained in:
Dan Hoerst 2022-06-07 12:12:28 -04:00
Коммит da2f70d060
262 изменённых файлов: 9388 добавлений и 0 удалений

83
.github/workflows/acceptance.yml поставляемый Normal file
Просмотреть файл

@ -0,0 +1,83 @@
name: acceptance
on:
push:
branches:
- main
pull_request:
jobs:
# Detects changes to any of the source files for entitlements-gitrepo-auditor-plugin
changes:
runs-on: ubuntu-latest
permissions:
contents: read
outputs:
has_change: ${{ steps.diff.outputs.has_change}}
steps:
- uses: actions/checkout@v2
- id: fetch-base
if: github.event_name == 'pull_request'
name: fetch the latest commit in the base branch to diff against
run: git fetch --no-tags --prune --depth=1 origin '+refs/heads/${{ github.base_ref }}:refs/remotes/origin/${{ github.base_ref }}'
- id: diff
if: github.event_name == 'pull_request'
name: diff against the base branch latest commit for specific paths
run: |
git diff \
origin/${{ github.base_ref }} \
HEAD \
-- \
'bin/**' \
'lib/**' \
'script/**' \
'spec/**' \
'vendor/**' \
'.ruby-version' \
'entitlements-gitrepo-auditor-plugin.gemspec' \
'Gemfile' \
'Gemfile.lock' \
> diff.txt
# If the diff file is not empty, it has changes.
[ -s diff.txt ] && echo "::set-output name=has_change::true" || echo "::set-output name=has_change::false"
- name: set has_change to true for push to main/master
if: github.event_name == 'push'
run: echo "::set-output name=has_change::true"
acceptance-suite:
needs: changes
runs-on: ubuntu-latest
name: runner / acceptance-tests
permissions:
contents: read
steps:
# If source files were not changed, we don't need the acceptance test suite
- name: bypass
if: ${{ needs.changes.outputs.has_change != 'true' }}
run: |
echo "✅ Bypassing acceptance tests - they are not required for this change"
- name: Check out code
if: ${{ needs.changes.outputs.has_change == 'true' }}
uses: actions/checkout@v2
# Use Docker layer caching for 'docker build' and 'docker-compose build' commands.
# https://github.com/satackey/action-docker-layer-caching/releases/tag/v0.0.11
- uses: satackey/action-docker-layer-caching@46d2c640b1d8ef50d185452ad6fb324e6bd1d052
if: ${{ needs.changes.outputs.has_change == 'true' }}
continue-on-error: true
- name: acceptance tests
if: ${{ needs.changes.outputs.has_change == 'true' }}
run: script/cibuild-entitlements-gitrepo-auditor-plugin-acceptance
- name: acceptance tests passed
run: echo "✅ The acceptance test suite has passed"

45
.github/workflows/codeql-analysis.yml поставляемый Normal file
Просмотреть файл

@ -0,0 +1,45 @@
name: "CodeQL"
on:
push:
branches: [ main ]
pull_request:
# The branches below must be a subset of the branches above
branches: [ main ]
schedule:
- cron: '25 4 * * 5'
jobs:
analyze:
name: Analyze
runs-on: ubuntu-latest
permissions:
actions: read
contents: read
security-events: write
strategy:
fail-fast: false
matrix:
language: [ 'ruby' ]
steps:
- name: Checkout repository
uses: actions/checkout@v2
# Initializes the CodeQL tools for scanning.
- name: Initialize CodeQL
uses: github/codeql-action/init@v1
with:
languages: ${{ matrix.language }}
# Autobuild attempts to build any compiled languages (C/C++, C#, or Java).
# If this step fails, then you should remove it and run the build manually (see below)
- name: Autobuild
uses: github/codeql-action/autobuild@v1
#- run: |
# make bootstrap
# make release
- name: Perform CodeQL Analysis
uses: github/codeql-action/analyze@v1

27
.github/workflows/lint.yml поставляемый Normal file
Просмотреть файл

@ -0,0 +1,27 @@
name: lint
on:
push:
branches:
- main
pull_request:
jobs:
rubocop:
name: runner / rubocop
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Check out code
uses: actions/checkout@v2
# https://github.com/ruby/setup-ruby/releases/tag/v1.87.0
- uses: ruby/setup-ruby@cf1a6dd2d8563b59c7007e381836fd252ab2ac5b
with:
ruby-version: 2.7.5
bundler-cache: true
- name: rubocop
run: bundle exec rubocop -c .rubocop.yml lib/ spec/

27
.github/workflows/test.yml поставляемый Normal file
Просмотреть файл

@ -0,0 +1,27 @@
name: test
on:
push:
branches:
- main
pull_request:
jobs:
rubocop:
name: runner / rspec
runs-on: ubuntu-latest
permissions:
contents: read
steps:
- name: Check out code
uses: actions/checkout@v2
# https://github.com/ruby/setup-ruby/releases/tag/v1.87.0
- uses: ruby/setup-ruby@cf1a6dd2d8563b59c7007e381836fd252ab2ac5b
with:
ruby-version: 2.7.5
bundler-cache: true
- name: rspec tests
run: script/test -d

19
.gitignore поставляемый Normal file
Просмотреть файл

@ -0,0 +1,19 @@
/.bundle
/vendor/gems
# Ignore binstubs
bin/*
!bin/.keep
# There's a place for local caching of container gems to make local builds faster.
# Keep the .keep file but not the gems themselves
vendor/container-gems/*
!vendor/container-gems/.keep
# Coverage reports
coverage/*
.*.swp
# Ignore JetBrains IDEs
.idea

12
.rubocop.yml Normal file
Просмотреть файл

@ -0,0 +1,12 @@
inherit_gem:
rubocop-github:
- config/default.yml
AllCops:
DisplayCopNames: true
TargetRubyVersion: 2.7.5
Exclude:
- 'bin/*'
- 'spec/acceptance/fixtures/**/*'
- 'spec/unit/fixtures/**/*'
- 'vendor/gems/**/*'

1
.ruby-version Normal file
Просмотреть файл

@ -0,0 +1 @@
2.7.5

5
Gemfile Normal file
Просмотреть файл

@ -0,0 +1,5 @@
# frozen_string_literal: true
source "https://rubygems.org"
gemspec

138
Gemfile.lock Normal file
Просмотреть файл

@ -0,0 +1,138 @@
PATH
remote: .
specs:
entitlements-gitrepo-auditor-plugin (0.1.0)
concurrent-ruby (= 1.1.9)
contracts (= 0.16.0)
faraday (>= 0.17.3, < 0.18)
net-ldap (~> 0.17.0)
octokit (~> 4.18)
optimist (= 3.0.0)
GEM
remote: https://rubygems.org/
specs:
activesupport (6.1.6)
concurrent-ruby (~> 1.0, >= 1.0.2)
i18n (>= 1.6, < 2)
minitest (>= 5.1)
tzinfo (~> 2.0)
zeitwerk (~> 2.3)
addressable (2.8.0)
public_suffix (>= 2.0.2, < 5.0)
ast (2.4.2)
concurrent-ruby (1.1.9)
contracts (0.16.0)
contracts-rspec (0.1.0)
crack (0.4.5)
rexml
diff-lcs (1.4.4)
docile (1.4.0)
entitlements (0.1.5.g6c8e3a79)
concurrent-ruby (= 1.1.9)
contracts (= 0.16.0)
faraday (>= 0.17.3, < 0.18)
net-ldap (~> 0.17.0)
octokit (~> 4.18)
optimist (= 3.0.0)
faraday (0.17.4)
multipart-post (>= 1.2, < 3)
hashdiff (1.0.1)
i18n (1.10.0)
concurrent-ruby (~> 1.0)
json (2.6.1)
minitest (5.15.0)
multipart-post (2.1.1)
net-ldap (0.17.0)
octokit (4.21.0)
faraday (>= 0.9)
sawyer (~> 0.8.0, >= 0.5.3)
optimist (3.0.0)
parallel (1.22.1)
parser (3.1.2.0)
ast (~> 2.4.1)
public_suffix (4.0.6)
rack (2.2.3)
rainbow (3.1.1)
rake (13.0.6)
regexp_parser (2.4.0)
rexml (3.2.5)
rspec (3.8.0)
rspec-core (~> 3.8.0)
rspec-expectations (~> 3.8.0)
rspec-mocks (~> 3.8.0)
rspec-core (3.8.0)
rspec-support (~> 3.8.0)
rspec-expectations (3.8.6)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.8.0)
rspec-mocks (3.8.2)
diff-lcs (>= 1.2.0, < 2.0)
rspec-support (~> 3.8.0)
rspec-support (3.8.3)
rubocop (1.29.1)
parallel (~> 1.10)
parser (>= 3.1.0.0)
rainbow (>= 2.2.2, < 4.0)
regexp_parser (>= 1.8, < 3.0)
rexml (>= 3.2.5, < 4.0)
rubocop-ast (>= 1.17.0, < 2.0)
ruby-progressbar (~> 1.7)
unicode-display_width (>= 1.4.0, < 3.0)
rubocop-ast (1.18.0)
parser (>= 3.1.1.0)
rubocop-github (0.17.0)
rubocop
rubocop-performance
rubocop-rails
rubocop-performance (1.13.3)
rubocop (>= 1.7.0, < 2.0)
rubocop-ast (>= 0.4.0)
rubocop-rails (2.14.2)
activesupport (>= 4.2.0)
rack (>= 1.1)
rubocop (>= 1.7.0, < 2.0)
ruby-progressbar (1.11.0)
rugged (0.27.5)
sawyer (0.8.2)
addressable (>= 2.3.5)
faraday (> 0.8, < 2.0)
simplecov (0.16.1)
docile (~> 1.1)
json (>= 1.8, < 3)
simplecov-html (~> 0.10.0)
simplecov-erb (0.1.1)
simplecov
simplecov-html (0.10.2)
tzinfo (2.0.4)
concurrent-ruby (~> 1.0)
unicode-display_width (2.1.0)
vcr (4.0.0)
webmock (3.4.2)
addressable (>= 2.3.6)
crack (>= 0.3.2)
hashdiff
zeitwerk (2.5.4)
PLATFORMS
ruby
x86_64-darwin-19
DEPENDENCIES
contracts-rspec (= 0.1.0)
entitlements (= 0.1.5.g6c8e3a79)
entitlements-gitrepo-auditor-plugin!
rake (= 13.0.6)
rspec (= 3.8.0)
rspec-core (= 3.8.0)
rubocop (= 1.29.1)
rubocop-github (= 0.17.0)
rubocop-performance (= 1.13.3)
rugged (= 0.27.5)
simplecov (= 0.16.1)
simplecov-erb (= 0.1.1)
vcr (= 4.0.0)
webmock (= 3.4.2)
BUNDLED WITH
2.2.24

73
README.md Normal file
Просмотреть файл

@ -0,0 +1,73 @@
# entitlements-gitrepo-auditor-plugin
[![acceptance](https://github.com/github/entitlements-gitrepo-auditor-plugin/actions/workflows/acceptance.yml/badge.svg)](https://github.com/github/entitlements-gitrepo-auditor-plugin/actions/workflows/acceptance.yml) [![test](https://github.com/github/entitlements-gitrepo-auditor-plugin/actions/workflows/test.yml/badge.svg)](https://github.com/github/entitlements-gitrepo-auditor-plugin/actions/workflows/test.yml) [![lint](https://github.com/github/entitlements-gitrepo-auditor-plugin/actions/workflows/lint.yml/badge.svg)](https://github.com/github/entitlements-gitrepo-auditor-plugin/actions/workflows/lint.yml) [![coverage](https://img.shields.io/badge/coverage-100%25-success)](https://img.shields.io/badge/coverage-100%25-success) [![style](https://img.shields.io/badge/code%20style-rubocop--github-blue)](https://github.com/github/rubocop-github)
`entitlements-gitrepo-auditor-plugin` is an [entitlements-app](https://github.com/github/entitlements-app) plugin allowing further auditing capabilities in entitlements by writing each deploy log to a separate GitHub repo.
## Usage
Your `entitlements-app` config `config/entitlements.yaml` runs through ERB interpretation automatically. You can extend your entitlements configuration to load plugins like so:
```
<%-
unless ENV['CI_MODE']
begin
require_relative "/data/entitlements/lib/entitlements-and-plugins"
rescue Exception
begin
require_relative "lib/entitlements-and-plugins"
rescue Exception
# We might not have the plugins installed and still want this file to be
# loaded. Don't raise anything but silently fail.
end
end
end
-%>
```
You can then define `lib/entitlements-and-plugins` like so:
```
#!/usr/bin/env ruby
# frozen_string_literal: true
ENV["BUNDLE_GEMFILE"] = File.expand_path("../../Gemfile", File.dirname(__FILE__))
require "bundler/setup"
require "entitlements"
# require entitlements plugins here
require "entitlements/auditor/gitrepo"
require "entitlements/util/gitrepo"
```
Any plugins defined in `lib/entitlements-and-plugins` will be loaded and used at `entitlements-app` runtime.
## Features
### Git Repo Auditing
You can add automatic auditing to a separate GitRepo by enabling the following `entitlements.yaml` config:
```
<%-
# NOTE: GITREPO_SSH_KEY must be base64 encoded.
sshkey = ENV.fetch("GITREPO_SSH_KEY")
shipper = ENV.fetch("GIT_SHIPPER", "<unknown person>")
what = ["entitlements", ENV.fetch("GIT_BRANCH", "<unknown branch>")].join("/")
sha = ENV.fetch("GIT_SHA1", "<unknown sha>")
url = "https://github.com/github/entitlements-config/commit/#{sha}"
commit_message = "#{shipper} deployed #{what} (#{url})"
-%>
auditors:
- auditor_class: GitRepo
checkout_directory: <%= ENV["GITREPO_CHECKOUT_DIRECTORY"] %>
commit_message: <%= commit_message %>
git_name: GitRepoUser
git_email: gitrepousers@users.noreply
person_dn_format: uid=%KEY%,ou=People,dc=github,dc=net
repo: github/entitlements-config-auditlog
sshkey: '<%= sshkey %>'
<%- end -%>
```
At the end of each `entitlements-app` run, the `entitlements-gitrepo-auditor-plugin` will write a commit to the repo defined above with the details of the deployment.

1
VERSION Normal file
Просмотреть файл

@ -0,0 +1 @@
0.1.0

0
bin/.keep Normal file
Просмотреть файл

Просмотреть файл

@ -0,0 +1,35 @@
# frozen_string_literal: true
Gem::Specification.new do |s|
s.name = "entitlements-gitrepo-auditor-plugin"
s.version = File.read("VERSION").chomp
s.summary = "Entitlements GitRepo Auditor"
s.description = ""
s.authors = ["GitHub, Inc. Security Ops"]
s.email = "opensource+entitlements-app@github.com"
s.license = "MIT"
s.files = Dir.glob("lib/**/*") + %w[VERSION]
s.homepage = "https://github.com/github/entitlements-gitrepo-auditor-plugin"
s.executables = %w[]
s.add_dependency "concurrent-ruby", "= 1.1.9"
s.add_dependency "contracts", "= 0.16.0"
s.add_dependency "faraday", ">= 0.17.3", "< 0.18"
s.add_dependency "net-ldap", "~> 0.17.0"
s.add_dependency "octokit", "~> 4.18"
s.add_dependency "optimist", "= 3.0.0"
s.add_development_dependency "contracts-rspec", "= 0.1.0"
s.add_development_dependency "entitlements", "0.1.5.g6c8e3a79"
s.add_development_dependency "rake", "= 13.0.6"
s.add_development_dependency "rspec", "= 3.8.0"
s.add_development_dependency "rspec-core", "= 3.8.0"
s.add_development_dependency "rubocop", "= 1.29.1"
s.add_development_dependency "rubocop-github", "= 0.17.0"
s.add_development_dependency "rubocop-performance", "= 1.13.3"
s.add_development_dependency "rugged", "= 0.27.5"
s.add_development_dependency "simplecov", "= 0.16.1"
s.add_development_dependency "simplecov-erb", "= 0.1.1"
s.add_development_dependency "vcr", "= 4.0.0"
s.add_development_dependency "webmock", "3.4.2"
end

0
lib/.keep Normal file
Просмотреть файл

0
lib/entitlements/.keep Normal file
Просмотреть файл

Просмотреть файл

Просмотреть файл

@ -0,0 +1,445 @@
# frozen_string_literal: true
# This audit provider dumps a sorted list of member DNs and group metadata to a file in a directory structure,
# and when the entitlements run is finished, commits the changes to the git repo.
require "base64"
module Entitlements
class Auditor
class GitRepo < Entitlements::Auditor::Base
include ::Contracts::Core
C = ::Contracts
# Setup method for git repo: this will clone the repo into the configured directory if
# it does not exist, or pull the latest changes from the configured directory if it does.
# We can also validate that the required parameters are supplied here.
#
# Takes no arguments.
#
# Returns nothing.
Contract C::None => C::Any
def setup
validate_options!
operation = File.directory?(checkout_directory) ? :pull : :clone
logger.debug "Preparing #{checkout_directory}"
@repo = Entitlements::Util::GitRepo.new(
repo: config["repo"],
sshkey: Base64.decode64(config["sshkey"]),
logger: logger
)
@repo.github = config["github_override"] if config["github_override"]
@repo.send(operation, checkout_directory)
@repo.configure(checkout_directory, config["git_name"], config["git_email"])
logger.debug "Directory #{checkout_directory} prepared"
end
# Commit method for git repo: this will write out all of the entitlements files to the
# configured directory, then do a git commit, and then push to GitHub.
#
# actions - Array of Entitlements::Models::Action (all requested actions)
# successful_actions - Set of DNs (successfully applied actions)
# provider_exception - Exception raised by a provider when applying (hopefully nil)
#
# Returns nothing.
Contract C::KeywordArgs[
actions: C::ArrayOf[Entitlements::Models::Action],
successful_actions: C::SetOf[String],
provider_exception: C::Or[nil, Exception]
] => C::Any
def commit(actions:, successful_actions:, provider_exception:)
raise "Must run setup method before running commit method" unless @repo
sync_changes = {}
valid_changes = {}
commitable_actions = actions_with_membership_change(actions)
action_hash = commitable_actions.map { |action| [action.dn, action] }.to_h
%w[update_files delete_files].each do |m|
send(
m.to_sym,
action_hash: action_hash,
successful_actions: successful_actions,
sync_changes: sync_changes,
valid_changes: valid_changes
)
end
# If there is anything out-of-sync and the provider did not throw an exception, create
# a special sync commit to update things.
if sync_changes.any?
if provider_exception
logger.warn "Not committing #{sync_changes.size} unrecognized change(s) due to provider exception"
else
logger.warn "Sync changes required: count=#{sync_changes.size}"
commit_changes(sync_changes, :sync, commit_message)
end
end
# If there are any valid changes, create a commit to update things.
if valid_changes.any?
logger.debug "Committing #{valid_changes.size} change(s) to git repository"
commit_changes(valid_changes, :valid, commit_message)
elsif sync_changes.empty?
logger.debug "No changes to git repository"
end
end
private
# The checkout directory from the configuration. Separated out here as a method so
# it can be more easily stubbed from tests.
#
# Takes no arguments.
#
# Returns a String with the checkout directory.
Contract C::None => String
def checkout_directory
config["checkout_directory"]
end
# Commit message - read from the provider's configuration. (This is so the commit
# message can be passed in as an ERB for flexibility.)
#
# Takes no arguments.
#
# Returns a String with the commit message.
Contract C::None => String
def commit_message
config.fetch("commit_message")
end
# Check the current calculation object for any added or updated groups. Break changes
# apart into sync changes and valid changes.
#
# action_hash - The hash of actions
# successful_actions - Set of DNs that were successfully updated/added/deleted
# sync_changes - The hash (will be updated)
# valid_changes - The hash (will be updated)
#
# Returns nothing.
Contract C::KeywordArgs[
action_hash: C::HashOf[String => Entitlements::Models::Action],
successful_actions: C::SetOf[String],
sync_changes: C::HashOf[String => C::Or[String, :delete]],
valid_changes: C::HashOf[String => C::Or[String, :delete]]
] => C::Any
def update_files(action_hash:, successful_actions:, sync_changes:, valid_changes:)
# Need to add nil entries onto the calculated hash for action == delete. These entries
# simply disappear from the calculated hash, but we need to iterate over them too.
iterable_hash = Entitlements::Data::Groups::Calculated.to_h.dup
action_hash.select { |dn, action| action.change_type == :delete }.each do |dn, _action|
iterable_hash[dn] = nil
end
iterable_hash.each do |dn, group|
filename = path_from_dn(dn)
target_file = File.join(checkout_directory, filename)
action = action_hash[dn]
if action.nil?
handle_no_action(sync_changes, valid_changes, filename, target_file, group)
elsif action.change_type == :delete
handle_delete(sync_changes, valid_changes, action, successful_actions, filename, target_file, dn)
elsif action.change_type == :add
handle_add(sync_changes, valid_changes, action, successful_actions, filename, target_file, dn, group)
elsif action.change_type == :update
handle_update(sync_changes, valid_changes, action, successful_actions, filename, target_file, dn, group)
else
# :nocov:
raise "Unhandled condition for action #{action.inspect}"
# :nocov:
end
end
end
# Find files that need to be deleted. All files deleted because of actions are handled in the
# 'updated_files' method. This method is truly meant for cleanup only.
#
# action_hash - The hash of actions
# successful_actions - Set of DNs that were successfully updated/added/deleted
# sync_changes - The hash (will be updated)
# valid_changes - The hash (will be updated)
#
# Returns nothing.
Contract C::KeywordArgs[
action_hash: C::HashOf[String => Entitlements::Models::Action],
successful_actions: C::SetOf[String],
sync_changes: C::HashOf[String => C::Or[String, :delete]],
valid_changes: C::HashOf[String => C::Or[String, :delete]]
] => C::Any
def delete_files(action_hash:, successful_actions:, sync_changes:, valid_changes:)
Dir.chdir checkout_directory
Dir.glob("**/*") do |child|
child_file = File.join(checkout_directory, child)
next unless File.file?(child_file)
next if File.basename(child) == "README.md"
# !! NOTE !!
# Defined actions (:add, :update, :delete) are handled in update_files. This
# logic only deals with files that exist and shouldn't and don't have action being
# taken upon them.
child_dn = dn_from_path(child)
if Entitlements::Data::Groups::Calculated.to_h.key?(child_dn)
# File is supposed to exist and it exists. Do nothing.
elsif action_hash[child_dn].nil?
# File is not supposed to exist, but it does, and there was no action concerning it.
# Set up sync change to delete file.
logger.warn "Sync change (delete #{child}) required"
sync_changes[child] = :delete
end
end
end
# For readability: Handle no-action logic.
def handle_no_action(sync_changes, valid_changes, filename, target_file, group)
group_expected_contents = group_contents_as_text(group)
if File.file?(target_file)
file_contents = File.read(target_file)
unless file_contents == group_expected_contents
logger.warn "Sync change (update #{filename}) required"
sync_changes[filename] = group_expected_contents
end
elsif group.member_strings.empty?
# The group does not currently exist in the file system nor is it created in the
# provider because it has no members. We can skip over this case.
else
logger.warn "Sync change (create #{filename}) required"
sync_changes[filename] = group_expected_contents
end
end
# For readability: Handle 'delete' logic.
def handle_delete(sync_changes, valid_changes, action, successful_actions, filename, target_file, dn)
group_expected_contents = group_contents_as_text(action.existing)
if File.file?(target_file)
file_contents = File.read(target_file)
if successful_actions.member?(dn)
if file_contents == group_expected_contents
# Good: The file had the correct prior content so it can just be deleted.
logger.debug "Valid change (delete #{filename}) queued"
valid_changes[filename] = :delete
else
# Bad: The file had incorrect prior content. Sync to the previous members and then delete it.
logger.warn "Sync change (update #{filename}) required"
sync_changes[filename] = group_expected_contents
logger.debug "Valid change (delete #{filename}) queued"
valid_changes[filename] = :delete
end
elsif file_contents == group_expected_contents
# Good: The file already had the correct prior content. Since the action was unsuccessful
# just skip this case doing nothing.
logger.warn "Skip change (delete #{filename}) due to unsuccessful action"
else
# Bad: The file had incorrect prior content. Wait for the successful run to sync the change.
logger.warn "Skip sync change (update #{filename}) due to unsuccessful action"
end
else
if successful_actions.member?(dn)
# Bad: The file didn't exist before but it should have. Create it now and then delete it.
logger.warn "Sync change (create #{filename}) required"
sync_changes[filename] = group_expected_contents
logger.debug "Valid change (delete #{filename}) queued"
valid_changes[filename] = :delete
else
# Bad: The file didn't exist before but it should have. Wait for the successful run to sync the change.
logger.warn "Skip sync change (create #{filename}) due to unsuccessful action"
end
end
end
# For readability: Handle 'add' logic.
def handle_add(sync_changes, valid_changes, action, successful_actions, filename, target_file, dn, group)
group_expected_contents = group_contents_as_text(group)
if File.file?(target_file)
if successful_actions.member?(dn)
# Weird case: The file was not supposed to be there but for some reason it is.
# Do a sync commit to remove the file (then a valid commit to add it back).
logger.warn "Sync change (delete #{filename}) required"
sync_changes[filename] = :delete
else
# Weird case: The file was there but the action to create the group was unsuccessful.
# Do nothing here, to let this get sync'd and updated when it completes successfully.
logger.warn "Skip sync change (delete #{filename}) due to unsuccessful action"
end
end
if successful_actions.member?(dn)
logger.debug "Valid change (create #{filename}) queued"
valid_changes[filename] = group_expected_contents
else
logger.warn "Skip change (add #{filename}) due to unsuccessful action"
end
end
# For readability: Handle 'update' logic.
def handle_update(sync_changes, valid_changes, action, successful_actions, filename, target_file, dn, group)
group_expected_contents = group_contents_as_text(group)
group_existing_contents = group_contents_as_text(action.existing)
if File.file?(target_file)
if successful_actions.member?(dn)
if File.read(target_file) == group_existing_contents
# Good: The file had the correct prior content so it can just be updated with the new content.
logger.debug "Valid change (update #{filename}) queued"
valid_changes[filename] = group_expected_contents
else
# Bad: The file had incorrect prior content. Sync to the previous members and then update it.
logger.warn "Sync change (update #{filename}) required"
sync_changes[filename] = group_existing_contents
logger.debug "Valid change (update #{filename}) queued"
valid_changes[filename] = group_expected_contents
end
elsif File.read(target_file) == group_existing_contents
# Good: The file already had the correct prior content. Since the action was unsuccessful
# just skip this case doing nothing.
logger.warn "Skip change (update #{filename}) due to unsuccessful action"
else
# Bad: The file had incorrect prior content. Wait for the successful run to sync the change.
logger.warn "Skip sync change (update #{filename}) due to unsuccessful action"
end
else
if successful_actions.member?(dn)
# Bad: The file didn't exist before but it should have. Create it now and then update it.
logger.warn "Sync change (create #{filename}) required"
sync_changes[filename] = group_existing_contents
logger.debug "Valid change (update #{filename}) queued"
valid_changes[filename] = group_expected_contents
else
# Bad: The file didn't exist before but it should have. Wait for the successful run to sync the change.
logger.warn "Skip sync change (create #{filename}) due to unsuccessful action"
end
end
end
# This defines the file format within this repository. Just dump the list of users
# and sort them, one per line.
#
# group - Entitlements::Models::Group object
#
# Returns a String with the members sorted and delimited by newlines.
Contract Entitlements::Models::Group => String
def member_strings_as_text(group)
if group.member_strings.empty?
return "# No members\n"
end
member_array = if config["person_dn_format"]
group.member_strings.map { |ms| config["person_dn_format"].gsub("%KEY%", ms).downcase }
else
group.member_strings.map(&:downcase)
end
member_array.sort.join("\n") + "\n"
end
# This defines the file format within this repository. Dump the metadata from the group, and return it as one
# metadata declaration per line ie "metadata_team_name = my_github_team"
#
# group - Entitlements::Models::Group object
#
# Returns a String with the metadata sorted and delimited by newlines.
Contract Entitlements::Models::Group => String
def metadata_strings_as_text(group)
begin
group_metadata = group.metadata
ignored_metadata = ["_filename"]
ignored_metadata.each do |metadata|
group_metadata.delete(metadata)
end
if group_metadata.empty?
return ""
end
metadata_array = group_metadata.map { |k, v| "metadata_#{k}=#{v}" }
return metadata_array.sort.join("\n") + "\n"
rescue Entitlements::Models::Group::NoMetadata
return ""
end
end
# This defines the file format within this repository. Grabs the full
# contents of an entitlements group - that is the members and the metadata - and returns it
#
# group - Entitlements::Models::Group object
#
# Returns a String with the content sorted and delimited by newlines.
Contract Entitlements::Models::Group => String
def group_contents_as_text(group)
group_members = member_strings_as_text(group)
group_metadata = metadata_strings_as_text(group)
group_members + group_metadata
end
# Make changes in the directory tree, then "git add" and "git commit" the changes
# with the specified commit message.
#
# changes - Hash of { filename => content } (or { filename => :delete })
# type - Either :sync or :valid
#
# Returns nothing.
Contract C::HashOf[String => C::Or[String, :delete]], C::Or[:sync, :valid], String => nil
def commit_changes(expected_changes, type, commit_message)
return if expected_changes.empty?
valid_changes = false
expected_changes.each do |filename, content|
target = File.join(checkout_directory, filename)
if content == :delete
# It's possible for two separate commits to the gitrepo to remove the same file, causing a race condition
# The first commit will delete the file from the gitrepo, and the second commit will fail with an empty commit
# For that reason, we only track a removal as a valid change if the file exists and would actually be removed
next unless File.exist?(target)
FileUtils.rm_f target
else
FileUtils.mkdir_p File.dirname(target)
File.open(target, "w") { |f| f.write(content) }
end
valid_changes = true
@repo.add(checkout_directory, filename)
end
return unless valid_changes
if type == :sync
@repo.commit(checkout_directory, "[sync commit] #{commit_message}")
else
@repo.commit(checkout_directory, commit_message)
end
@repo.push(checkout_directory)
end
# Validate the options in 'config'. Raise an error if options are invalid.
#
# Takes no arguments.
#
# Returns nothing.
# :nocov:
Contract C::None => nil
def validate_options!
require_config_keys %w[checkout_directory commit_message git_name git_email repo sshkey]
unless config["repo"] =~ %r{\A([^/]+)/([^/]+)\z}
configuration_error "'repo' must be of the form 'organization/reponame'"
end
begin
Base64.decode64(config["sshkey"])
rescue => e
configuration_error "'sshkey' could not be base64 decoded: #{e.class} #{e.message}"
end
nil
end
# :nocov:
end
end
end

Просмотреть файл

@ -0,0 +1,227 @@
# frozen_string_literal: true
# NOTE: This currently does NOT use "rugged" because we want to use SSH to connect to GitHub,
# but cannot be assured that "rugged" is compiled with SSH support everywhere this might run.
# Hence, "open3" is used to access an assumed "git" binary.
require "fileutils"
require "open3"
require "shellwords"
require "tmpdir"
module Entitlements
class Util
class GitRepo
include ::Contracts::Core
C = ::Contracts
class CommandError < StandardError; end
# This is hard-coded to use GitHub, just because. However this is here to support
# overriding this if needed (e.g. acceptance tests).
attr_accessor :github
# Constructor.
#
# repo - Name of the repo on GitHub (e.g. github/entitlements-audit)
# sshkey - Private SSH key for a user with push access to the repo
# logger - Logger object
#
# Returns nothing.
Contract C::KeywordArgs[
repo: String,
sshkey: String,
logger: C::Maybe[C::Or[Logger, Entitlements::Auditor::Base::CustomLogger]]
] => C::Any
def initialize(repo:, sshkey:, logger: Entitlements.logger)
@logger = logger
@repo = repo
@sshkey = sshkey
@github = "git@github.com:"
end
# Run "git add" on a file.
#
# dir - A String with the path where this is to take place.
# filename - File name, relative to dir, to be added.
#
# Returns nothing.
Contract String, String => nil
def add(dir, filename)
validate_git_repository!(dir)
git(dir, ["add", filename])
nil
end
# Clone git repo into the specified directory.
#
# dir - A String with the path where this is to take place.
#
# Returns nothing.
Contract String => nil
def clone(dir)
if File.exist?(dir)
raise Errno::EEXIST, "Cannot clone to #{dir}: already exists"
end
logger.debug "Cloning from GitHub to #{dir}"
FileUtils.mkdir_p(dir)
git(dir, ["clone", repo_url, "."], ssh: true)
nil
end
# Commit to the repo.
#
# dir - A String with the path where this is to take place.
# commit_message - A String with the commit message.
#
# Returns nothing.
Contract String, String => nil
def commit(dir, commit_message)
validate_git_repository!(dir)
git(dir, ["commit", "-m", commit_message])
nil
end
# Configure the name and e-mail address in the repo, so git commit knows what to use.
#
# dir - A String with the path where this is to take place.
# name - A String to pass to user.name
# email - A String to pass to user.email
#
# Returns nothing.
Contract String, String, String => nil
def configure(dir, name, email)
validate_git_repository!(dir)
logger.debug "Configuring #{dir} with name=#{name.inspect} email=#{email.inspect}"
git(dir, ["config", "user.name", name])
git(dir, ["config", "user.email", email])
nil
end
# Pull the latest from GitHub.
#
# dir - A String with the path where this is to take place.
#
# Returns nothing.
Contract String => nil
def pull(dir)
validate_git_repository!(dir)
logger.debug "Pulling from GitHub to #{dir}"
git(dir, ["reset", "--hard", "HEAD"])
git(dir, ["clean", "-f", "-d"])
git(dir, ["pull"], ssh: true)
nil
end
# Push the branch to GitHub.
#
# dir - A String with the path where this is to take place.
#
# Returns nothing.
Contract String => nil
def push(dir)
validate_git_repository!(dir)
logger.debug "Pushing to GitHub from #{dir}"
git(dir, ["push", "origin", "master"], ssh: true)
nil
end
private
attr_reader :repo, :sshkey, :logger
# Helper method to refer to the repository on GitHub.
#
# Takes no arguments.
#
# Returns a String with the URL on GitHub.
Contract C::None => String
def repo_url
"#{github}#{repo}.git"
end
# Helper to validate that a particular directory contains a git repository.
#
# dir - Directory where the command should be run.
#
# Returns nothing (but may raise Errno::ENOENT).
Contract String => nil
def validate_git_repository!(dir)
return if File.directory?(dir) && File.directory?(File.join(dir, ".git"))
raise Errno::ENOENT, "Cannot pull in #{dir}: does not exist or is not a git repo"
end
# Run a git command.
#
# dir - Directory where the command should be run.
# args - An Array of Strings with the command line arguments.
# options - Additional options?
#
# Returns a hash of { stdout: String, stderr: String, status: Integer }
Contract String, C::ArrayOf[String], C::Maybe[C::HashOf[Symbol => C::Any]] => C::HashOf[Symbol => C::Any]
def git(dir, args, options = {})
unless File.directory?(dir)
raise Errno::ENOENT, "Attempted to run 'git' in non-existing directory #{dir}!"
end
commandline = ["git", args].flatten.map { |str| Shellwords.escape(str) }.join(" ")
out, err, code = open3_git_execute(dir, commandline, options.fetch(:ssh, false))
if code.exitstatus != 0 && options.fetch(:raise_on_error, true)
if out && !out.empty?
out.split("\n").reject { |str| str.strip.empty? }.each { |str| logger.warn "[stdout] #{str}" }
end
if err && !err.empty?
err.split("\n").reject { |str| str.strip.empty? }.each { |str| logger.warn "[stderr] #{str}" }
end
logger.fatal "Command failed (#{code.exitstatus}): #{commandline}"
raise CommandError, "git command failed"
end
{ stdout: out, stderr: err, status: code.exitstatus }
end
# Actually execute a command using open3. This handles wrapping the SSH key and git.
#
# dir - Directory where to run the command
# commandline - Commands to execute (must be properly escapted)
# ssh - True to set up a temporary directory and do the SSH key, false to skip this.
#
# Returns STDOUT, STDERR, EXITSTATUS
Contract String, String, C::Maybe[C::Bool] => [String, String, Process::Status]
def open3_git_execute(dir, commandline, ssh = false)
logger.debug "Execute: #{commandline}"
unless ssh
return Open3.capture3(commandline, chdir: dir)
end
begin
# Replace GIT_SSH with our custom SSH wrapper that installs the key and disables anything
# else custom that might be going on in the environment. Turn off prompts for the SSH key for
# github.com being trusted or not, only use the provided key as the identity, and ignore any
# ~/.ssh/config file the user running this might have set up.
tempdir = Dir.mktmpdir
File.open(File.join(tempdir, "key"), "w") { |f| f.write(sshkey) }
File.open(File.join(tempdir, "ssh"), "w") do |f|
f.puts "#!/bin/sh"
f.puts "exec /usr/bin/ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null \\"
f.puts " -o IdentityFile=#{Shellwords.escape(File.join(tempdir, 'key'))} -o IdentitiesOnly=yes \\"
f.puts " -F /dev/null \\"
f.puts " \"$@\""
end
FileUtils.chmod(0400, File.join(tempdir, "key"))
FileUtils.chmod(0700, File.join(tempdir, "ssh"))
# Run the command in the directory `dir` with GIT_SSH pointed at the wrapper script built above.
# Returns STDOUT, STDERR, EXITSTATUS.
Open3.capture3({ "GIT_SSH" => File.join(tempdir, "ssh") }, commandline, chdir: dir)
ensure
# Always kill the temporary directory after running, no matter what happened.
FileUtils.remove_entry_secure(tempdir)
end
end
end
end
end

15
script/bootstrap Executable file
Просмотреть файл

@ -0,0 +1,15 @@
#!/bin/bash
set -e
set -x
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && cd .. && pwd )"
cd "$DIR"
export PATH=/usr/share/rbenv/shims:$PATH
export RBENV_VERSION="$(cat .ruby-version)"
rm -rf "${DIR}/.bundle"
# Using Deprecated Flags to avoid pulling from upstream
bundle install --path vendor/gems --local --clean
bundle binstubs rake rspec-core rubocop

7
script/cibuild Executable file
Просмотреть файл

@ -0,0 +1,7 @@
#!/bin/bash
set -e
cd "$(dirname "$0")/.."
echo "Heres some output"
docker build -t entitlements-gitrepo-auditor-plugin -f spec/acceptance/Dockerfile.entitlements-gitrepo-auditor-plugin .
docker run -w "/data/entitlements" entitlements-gitrepo-auditor-plugin bash -c "script/test"

Просмотреть файл

@ -0,0 +1,78 @@
#!/bin/bash
export DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && cd .. && pwd )"
export APP_NAME="entitlements-gitrepo-auditor-plugin"
export GIT_SERVER_NAME="git-server"
export LDAP_SERVER_NAME="ldap-server"
if [ ! -f "${DIR}/spec/acceptance/Dockerfile.${APP_NAME}" ]; then
echo "No Dockerfile.${APP_NAME} was found"
exit 255
fi
begin_fold() {
local tag="$1"
echo "%%%FOLD {${tag}}%%%" 1>&2
set -x
}
end_fold() {
set +x
echo "%%%END FOLD%%%" 1>&2
}
docker_compose() {
cd "$DIR" && docker-compose -f "$DIR/spec/acceptance/docker-compose.yml" "$@"
}
unset DOCKER_COMPOSE_NEEDS_SHUTDOWN
cleanup() {
if [ -n "$DOCKER_COMPOSE_NEEDS_SHUTDOWN" ]; then
begin_fold "Logs from ${GIT_SERVER_NAME} container"
docker_compose logs --no-color "$GIT_SERVER_NAME" 1>&2
end_fold
begin_fold "Logs from ${LDAP_SERVER_NAME} container"
docker_compose logs --no-color "$LDAP_SERVER_NAME" 1>&2
end_fold
begin_fold "Shutting down docker-compose"
docker_compose down 1>&2
end_fold
fi
unset DOCKER_COMPOSE_NEEDS_SHUTDOWN
}
trap cleanup EXIT
set -e
begin_fold "Building/updating ${APP_NAME} container"
docker_compose build "${APP_NAME}"
end_fold
export DOCKER_COMPOSE_NEEDS_SHUTDOWN="true"
begin_fold "Starting ${LDAP_SERVER_NAME} container"
docker_compose up --force-recreate -d "${LDAP_SERVER_NAME}"
end_fold
begin_fold "Starting ${GIT_SERVER_NAME} container"
docker_compose up --force-recreate -d "${GIT_SERVER_NAME}"
end_fold
# This is where the tests actually run
echo "Starting ${APP_NAME} acceptance test container" 1>&2
docker_compose run "${APP_NAME}" "/acceptance/support/run-app.sh" && exitcode=$? || exitcode=$?
# Display logs from containers and shut down docker-compose.
cleanup
# We're done!
echo ""
echo "*****************************************************************"
echo "${APP_NAME} acceptance exit status = ${exitcode}"
echo "*****************************************************************"
echo ""
exit $exitcode

10
script/lib/fold.sh Normal file
Просмотреть файл

@ -0,0 +1,10 @@
begin_fold() {
local tag="$1"
echo "%%%FOLD {${tag}}%%%" 1>&2
set -x
}
end_fold() {
set +x
echo "%%%END FOLD%%%" 1>&2
}

76
script/test Executable file
Просмотреть файл

@ -0,0 +1,76 @@
#!/bin/bash
# run script/test -h for help
set -e
function usage()
{
echo -e "\t ================== script/test usage =================="
echo -e "\t-h --help : displays help message"
echo -e "\t-d --disable-bootstrap : disables bootstrap"
echo -e "\n\t Suggested flags for development: script/test -d"
}
while [ "$1" != "" ]; do
PARAM=`echo $1 | awk -F= '{print $1}'`
VALUE=`echo $1 | awk -F= '{print $2}'`
case $PARAM in
-h | --help)
usage
exit
;;
-k | --no-linter)
no_linter=1
;;
-d | --disable-bootstrap)
no_bootstrap=1
;;
*)
echo "ERROR: unknown parameter \"$PARAM\""
usage
exit 1
;;
esac
shift
done
DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && cd .. && pwd )"
export PATH=/usr/share/rbenv/shims:$PATH
export RBENV_VERSION="$(cat "${DIR}/.ruby-version")"
TRASHDIR=$(mktemp -d /tmp/cibuild.XXXXXXXXXXXXXXXXXX)
cleanup() {
rm -rf "$TRASHDIR"
}
trap cleanup EXIT
cd "$DIR"
. "${DIR}/script/lib/fold.sh"
if [[ -z $no_bootstrap ]]; then
# bootstrap
begin_fold "Bootstrapping"
./script/bootstrap
end_fold
else
echo -e "\nBypass Bootstrap"
fi
bundle exec rspec spec/unit && rspec_exit=$? || rspec_exit=$?
cat "$DIR/coverage/coverage.txt"
grep -q "You're all set, friend" "$DIR/coverage/coverage.txt" && cov_exit=0 || cov_exit=1
echo ""
echo "---------------------------------------"
echo "Summary Results"
echo "---------------------------------------"
echo ""
echo "rspec: exitcode=${rspec_exit}"
echo "coverage: exitcode=${cov_exit}"
[ $rspec_exit -gt 0 ] && exit 1
[ $cov_exit -gt 0 ] && exit 1
exit 0

148
script/vendor-gem Executable file
Просмотреть файл

@ -0,0 +1,148 @@
#!/bin/sh
#/ Usage: script/vendor-gem [-r <rev>] [-n <gem>] [-d <directory>] <git-url>
#/ Build a gem for the given git repository and stick it in vendor/cache. With -r, build
#/ the gem at the branch, tag, or SHA1 given. With no -r, build the default HEAD.
#/ With -d, build the gem at the given directory within the repository.
#/
#/ This command is used in situations where you'd typically use a :git bundler
#/ source which should not be used in the main github app (even for development gems).
set -e
[[ $TRACE ]] && set -x
# write out compare url for review
[ $# -eq 0 ] && set -- --help
# parse args
rev=master
directory="."
while [ $# -gt 0 ]; do
case "$1" in
-d)
directory=$2
shift 2
;;
-r)
rev=$2
shift 2
;;
-n)
gem=$2
shift 2
;;
-h|--help)
grep ^#/ <"$0" |cut -c4-
exit
;;
*)
url="$1"
shift
;;
esac
done
if [ -z "$url" ]; then
echo "error: no git url given. see $0 --help for usage." 1>&2
exit 1
fi
repo=$(echo "$url" | sed 's@^\(https://github\.com.*\)\.git$@\1@')
if [ -z "$gem" ]; then
gem=$(basename "$url" .git)
fi
# the RAILS_ROOT directory
root=$(cd $(dirname "$0")/.. && pwd)
cd "$root"
gem_directory="$root/tmp/gems/$gem/$directory"
# clone the repo under tmp, clean up on exit
echo "Cloning $url for gem build"
mkdir -p "tmp/gems/$gem"
# go in and build the gem using the HEAD version, clean up this tmp dir on exit
echo "Building $gem"
(
cd "tmp/gems/$gem"
git init -q
git fetch -q -fu "$url" "+refs/*:refs/*"
git reset --hard HEAD
git clean -df
git checkout "$rev"
git submodule update --init
git --no-pager log -n 1
cd "$gem_directory"
gemspec=$(ls -1 *.gemspec | head -1)
echo "Building $gemspec"
gemname=$(basename "$gemspec" .gemspec)
echo $gemname > vendor-gem-name
# tag name + number of commits on top of tag + tree sha
GEM_VERSION=""
# No tags
if [ -z "${GEM_VERSION}" ]
then
gem_version=$(ruby -e "require 'rubygems'; spec=eval(File.read('$gemspec')); print spec.version.to_s")
tree_sha=$(git show --quiet --format=format:%t $rev)
GEM_VERSION="${gem_version}.g${tree_sha}"
fi
if [ -z "${GEM_VERSION}" ]
then
echo "couldn't determine the gem version from \"$gemspec\""
exit 1
fi
export GEM_VERSION
# build a wrapping gemspec that adds the sha1 version to the gem version
# unless the gemspec references the GEM_VERSION environment variable
# in which case we assume this is handled explicitly in the gemspec itself
if ! grep -q "GEM_VERSION" < $gemspec
then
cat <<-RUBY > vendor.gemspec
require 'rubygems'
spec = eval(File.read("$gemspec"))
spec.version = "$GEM_VERSION"
spec
RUBY
gem build vendor.gemspec
else
gem build $gemspec
fi
cd "$root/tmp/gems/$gem"
# Bump gem version in Gemfile (and deal with OS X sed differences)
sed -i -e "s/^gem ['\"]$gemname['\"],\( *\)['\"]\([^'\"]*\)['\"]/gem \"$gemname\",\\1\"$GEM_VERSION\"/" ../../../Gemfile
if [ `uname` = 'Darwin' ]; then
rm -f "../../../Gemfile-e"
fi
)
[ $? -eq 0 ] || exit 1
# get the gem name determined in the subprocess
gemname=$(cat "$gem_directory/vendor-gem-name")
# record old gem ref before deleting
oldref=$(ls vendor/cache/$gemname-*.gem | grep -o -E -e "g[0-9a-f]{7}" | cut -c 2-)
# remove any existing gems and add the newly built gem
if [ -n "$gemname" ]; then
git rm -f vendor/cache/$gemname*.gem 2>/dev/null || true
cp "$gem_directory/$gemname"*.gem vendor/cache
git add vendor/cache/$gemname*
fi
# get new gem ref
newref=$(ls vendor/cache/$gemname-*.gem | grep -o -E -e "g[0-9a-f]{7}" | cut -c 2-)
# write out compare url for review
echo "$repo/compare/$oldref...$newref"
rm -rf "tmp"
bundle update --local $gemname
git add Gemfile Gemfile.lock

Просмотреть файл

@ -0,0 +1,26 @@
FROM ruby:2.7.5-buster
LABEL maintainer="GitHub Security Ops <opensource+entitlements-app@github.com>"
ENV HOME /root
ENV RELEASE=buster
ENV container docker
WORKDIR /data/entitlements
# Install dependency packages for bootstrapping and running...
RUN apt-get update && DEBIAN_FRONTEND=noninteractive apt-get install -y \
build-essential \
cmake \
ldap-utils
# Install bundler
RUN gem install bundler
# Bootstrap files and caching for speed
COPY "vendor/cache/" "/data/entitlements/vendor/cache/"
COPY "script/" "/data/entitlements/script/"
COPY [".rubocop.yml", ".ruby-version", "entitlements-gitrepo-auditor-plugin.gemspec", "Gemfile", "Gemfile.lock", "VERSION", "/data/entitlements/"]
RUN ./script/bootstrap
# Source Files
COPY "bin/" "/data/entitlements/bin/"
COPY "lib/" "/data/entitlements/lib/"
COPY "spec/" "/data/entitlements/spec/"

Просмотреть файл

@ -0,0 +1,3 @@
# CA for acceptance
Password for every key: `kittens` (what else? :smile_cat:)

Просмотреть файл

@ -0,0 +1,35 @@
-----BEGIN CERTIFICATE-----
MIIGJDCCBAygAwIBAgIJAKHrJtknH6gDMA0GCSqGSIb3DQEBCwUAMIGeMQswCQYD
VQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNU2FuIEZyYW5j
aXNjbzEVMBMGA1UECgwMR2l0SHViLCBJbmMuMSwwKgYDVQQLDCNlbnRpdGxlbWVu
dHMgYXBwIGFjY2VwdGFuY2UgdGVzdCBDQTEdMBsGA1UEAwwUYWNjZXB0YW5jZS1j
YS5naXRodWIwHhcNMTgwMzAxMjE0MDAzWhcNMzgwMjI0MjE0MDAzWjCBnjELMAkG
A1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDVNhbiBGcmFu
Y2lzY28xFTATBgNVBAoMDEdpdEh1YiwgSW5jLjEsMCoGA1UECwwjZW50aXRsZW1l
bnRzIGFwcCBhY2NlcHRhbmNlIHRlc3QgQ0ExHTAbBgNVBAMMFGFjY2VwdGFuY2Ut
Y2EuZ2l0aHViMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA55O7ULc/
WQySiMxs9Y8EZVr6hGSJZEUUm7gk42dUSejvj/gCE52AhYUUR5ZQGAd5hZLKNvqH
qunLlRzFqziVo9uQ+EBnEalepO58ohhpzVlzSl4hxlPs9lO6L9owN28xH52DVnsx
G1GzOlZnnhI7nmxui+G9v0J0h5JVotqsYq7PKniovgP7XIg42EvrqYjhaCw53k7y
cgQL1OCxQF+ytiFFNnFrYlHqIZthOLAEP/OHGYZAidZuFzNJso6wEdCe0sYUZtHt
8aX1mWC6CqnaWoAAzyj7h4rwqXo/SqF25G1EKG3AjVUAl33Ai4J1PSJVdETYCV5w
ARcD6gIacDFO1a2bN54nQ/Oke8Yb5nAVuNrMFe5/gNZCQ2WTKYHUm8G8FbdsKs98
8guxfrewGRblQLUg3NRZQXupPXYi5Wy+d+TEtbYTAZi/mq+S16aOW32MALM6z/85
B8qCQUEM00K5GcpZAn3GnuWv1Pr79MQ2Fj5h40lJU4u3zDTKF1xNE4XOaIKldZlS
YJuJ0JKGF47MYxxa2ywxIWKM1+ukFMsc7XSlWXpvecCmWXvEbq4QkUHvGs//tWMW
6+hXc7zT3I6HxtHw+dllvGvkdP2KkS/SdJ4VDI+sK33dV0PqZs/O5c1GwpiCyXeY
mZpcOktXyjAe1iutVemYoNowNU4tzbqse8sCAwEAAaNjMGEwHQYDVR0OBBYEFEHP
qR0y/D7SMWwxSnZ7sh60TUvqMB8GA1UdIwQYMBaAFEHPqR0y/D7SMWwxSnZ7sh60
TUvqMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEB
CwUAA4ICAQBWxFhxvqpnel7AGhiB/kk1B792TZ83WB7QIDEXjV21eylvdQTCF5tM
3U3U5DsbxsyDW7pG5TykQOc83Z1F4AGUB2YyjMmsU5702RX3aBoH9J8wJ4dVoDWn
eevNXgR1WNpXsk3XOmunGIHEFSfEbZK9KAKOCAIP3CVUvKzS1rjlfpU+OS+qhrq8
EIIDSH4Twz25NHKTp/1Qq7YOeDrShkWKC5EWIXi3K85NKbJ6R7ulluDsv+alfAd5
0Y4RLKkDmrDQfBnQcMFmsgZmZ4/NfZPO/1siDsyTPIm/58w0pXKEyhQBi9pd/8PM
h8kzktldJFP5cPTSMz0hGMxUft5uFzHA4dAsuAUKo/zshpukjTYJW4Q8fykQ33tn
bqxheuLZO45rJo4jP1Nq/7g8yVXRae5JoxoYKEeciWW+ept2ygrQb/bUmoSWabQI
qX/TUzheRPB9TDBuRfQSHrxZb7EHTbB7E5GKbEEmFDsoB9vMcvg2k+OAmooNVtGO
s351Irsm2EBinlRBKIbej1am2pn2F96aVw5T1UJxlFGBPc6WgEOsWXtelwN2MOOs
7dyLMwjhEa775vXdcFwN15rX4MPOA2nGK+jpNrreHexv3r5dXSnOlESOC0sxMDgu
vLRJaJ2JnnuoDAvhaw6AOwzbwVGDHYl2ClUbKz7Iy5YwvF25khLswQ==
-----END CERTIFICATE-----

Просмотреть файл

@ -0,0 +1 @@
V 371116214418Z 1000 unknown /C=US/ST=California/O=GitHub, Inc./OU=entitlements app acceptance test CA/CN=intermediate-ca.github

Просмотреть файл

@ -0,0 +1 @@
unique_subject = yes

Просмотреть файл

Просмотреть файл

@ -0,0 +1,70 @@
-----BEGIN CERTIFICATE-----
MIIGCjCCA/KgAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwgZ4xCzAJBgNVBAYTAlVT
MRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1TYW4gRnJhbmNpc2NvMRUw
EwYDVQQKDAxHaXRIdWIsIEluYy4xLDAqBgNVBAsMI2VudGl0bGVtZW50cyBhcHAg
YWNjZXB0YW5jZSB0ZXN0IENBMR0wGwYDVQQDDBRhY2NlcHRhbmNlLWNhLmdpdGh1
YjAeFw0xODAzMDEyMTQ0MThaFw0zNzExMTYyMTQ0MThaMIGIMQswCQYDVQQGEwJV
UzETMBEGA1UECAwKQ2FsaWZvcm5pYTEVMBMGA1UECgwMR2l0SHViLCBJbmMuMSww
KgYDVQQLDCNlbnRpdGxlbWVudHMgYXBwIGFjY2VwdGFuY2UgdGVzdCBDQTEfMB0G
A1UEAwwWaW50ZXJtZWRpYXRlLWNhLmdpdGh1YjCCAiIwDQYJKoZIhvcNAQEBBQAD
ggIPADCCAgoCggIBAJZfDROyejD2AKheJUyAonf44Li8cAtbr6vCZ4/RyvoPiYD/
uJBBkV09/y3ldkQgHBt9zr7SE4BKjJI/w+X1bo26bD7RvRaC8gxUrT5ym5cJAXaf
1/QXoLiORxlK4F1TZKb8anFvNtS5nZ8Bzyxewm65cDUlyZJhMTBWTSs8qIXHSL0D
PaqKytnQCmtGCQYdb0qPV/aQpmlw8oW1mkdQTiJy5getBh/eDKQcC+owdl+ZvDOd
sFpcYWY5VgxdUTmnNQRRLUW55SMJJBppdxveLcMQOb43W9FBNL4pkSZ2yC+0ES/2
0FI7ydixucqeu5HPpS3eRPTkr3ATtO685LMsAAfn0AlLlnQ2fLMNZWD7bYtoNWSd
uxpZrVJhsAqTFHd/bx/aSPRdYDwoS9bIYin8uEUx7LQNX9/viO7NDcS6Kor7Lpu4
kqy7HvSSgoY6bDuGm/mexzOL9IljHac9ztuoeCDa/Gca57asu4pp5mWZnBgHfIu9
U9fxiqadTmHHYgXgEB2SXaSM0GIwy7014L3Bpsdlp/4ywTaOpxsiJntHlZLfw5Jw
LJA696xq6pQl7vkdkDm5UF2BH+dk3wuRX1MCCbim1CwGtwws4UR+NQH6A5CKfBbL
VTOLO4nqe7X7/u+s7p1McI+LPuMnfM1eu5yFblmvebNggcLpKOPea+ClqIIlAgMB
AAGjZjBkMB0GA1UdDgQWBBSw2FmWIrihGNPV0KKeQO6t/R9L8zAfBgNVHSMEGDAW
gBRBz6kdMvw+0jFsMUp2e7IetE1L6jASBgNVHRMBAf8ECDAGAQH/AgEAMA4GA1Ud
DwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAgEA3mt0BFljOxA2HuXV/vXdGBQY
ErR2vGZNvS0DMBhBBZcWaILesFeBEiHxLXlDcSisvsK2LsN6s3N8AYPY9s6f6XQ1
amSG9osfTouS2y/JqO3bbJSjL/pjz1/s1x/d9PwYPlEFeCniihAbwpQiYoyec0wh
ihQ1vDs4wQBLD+Gj+gYhnUf35OWhBjVw+iu0/oIxjdmQEQS1Qe/zimk+CpmdGf5u
rNWKDxs5TSskvCIwBdzh/hCvVuzk7fATc1pj5IaGi8I5o5070O4OJ5O2vLnKuwQw
pr7AYRGvew08xaMKVXhnBa9rNyynwb6u6vOeks8C6WQF14i+0WPPk/vcyfQZv6t6
lpD8kalzV94MbIM27HFY0dgboIhYFYJ31RGiC8lq1JYKdeBY2Z8eKRbmwrfvDiYU
CYAVkYH2QHD3a/H5fuB0JR20Tt82+NKKsH+fZO+kCMRDRpmRzG/H7Aiahs4gwjqq
29jTFg2NGYyoBfyQELuHSM/iW7reHdg/F1WqUW7AGmoAtf0Jk1PGfIJbczRAGYqS
FWh1X9nHvh51jg8arHPaRiYeLuSsjkYvnQGVhNnb+0q6M1H7tHZfKahuuUKeem4+
5l2eDeY3FlijQ6jtHOF4HsfJMlDTFLb6Adtl46Quh6zFJjkApldl6L9IuAbSffHV
Kpfjbv8qMtY2qx/pYI0=
-----END CERTIFICATE-----
-----BEGIN CERTIFICATE-----
MIIGJDCCBAygAwIBAgIJAKHrJtknH6gDMA0GCSqGSIb3DQEBCwUAMIGeMQswCQYD
VQQGEwJVUzETMBEGA1UECAwKQ2FsaWZvcm5pYTEWMBQGA1UEBwwNU2FuIEZyYW5j
aXNjbzEVMBMGA1UECgwMR2l0SHViLCBJbmMuMSwwKgYDVQQLDCNlbnRpdGxlbWVu
dHMgYXBwIGFjY2VwdGFuY2UgdGVzdCBDQTEdMBsGA1UEAwwUYWNjZXB0YW5jZS1j
YS5naXRodWIwHhcNMTgwMzAxMjE0MDAzWhcNMzgwMjI0MjE0MDAzWjCBnjELMAkG
A1UEBhMCVVMxEzARBgNVBAgMCkNhbGlmb3JuaWExFjAUBgNVBAcMDVNhbiBGcmFu
Y2lzY28xFTATBgNVBAoMDEdpdEh1YiwgSW5jLjEsMCoGA1UECwwjZW50aXRsZW1l
bnRzIGFwcCBhY2NlcHRhbmNlIHRlc3QgQ0ExHTAbBgNVBAMMFGFjY2VwdGFuY2Ut
Y2EuZ2l0aHViMIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA55O7ULc/
WQySiMxs9Y8EZVr6hGSJZEUUm7gk42dUSejvj/gCE52AhYUUR5ZQGAd5hZLKNvqH
qunLlRzFqziVo9uQ+EBnEalepO58ohhpzVlzSl4hxlPs9lO6L9owN28xH52DVnsx
G1GzOlZnnhI7nmxui+G9v0J0h5JVotqsYq7PKniovgP7XIg42EvrqYjhaCw53k7y
cgQL1OCxQF+ytiFFNnFrYlHqIZthOLAEP/OHGYZAidZuFzNJso6wEdCe0sYUZtHt
8aX1mWC6CqnaWoAAzyj7h4rwqXo/SqF25G1EKG3AjVUAl33Ai4J1PSJVdETYCV5w
ARcD6gIacDFO1a2bN54nQ/Oke8Yb5nAVuNrMFe5/gNZCQ2WTKYHUm8G8FbdsKs98
8guxfrewGRblQLUg3NRZQXupPXYi5Wy+d+TEtbYTAZi/mq+S16aOW32MALM6z/85
B8qCQUEM00K5GcpZAn3GnuWv1Pr79MQ2Fj5h40lJU4u3zDTKF1xNE4XOaIKldZlS
YJuJ0JKGF47MYxxa2ywxIWKM1+ukFMsc7XSlWXpvecCmWXvEbq4QkUHvGs//tWMW
6+hXc7zT3I6HxtHw+dllvGvkdP2KkS/SdJ4VDI+sK33dV0PqZs/O5c1GwpiCyXeY
mZpcOktXyjAe1iutVemYoNowNU4tzbqse8sCAwEAAaNjMGEwHQYDVR0OBBYEFEHP
qR0y/D7SMWwxSnZ7sh60TUvqMB8GA1UdIwQYMBaAFEHPqR0y/D7SMWwxSnZ7sh60
TUvqMA8GA1UdEwEB/wQFMAMBAf8wDgYDVR0PAQH/BAQDAgGGMA0GCSqGSIb3DQEB
CwUAA4ICAQBWxFhxvqpnel7AGhiB/kk1B792TZ83WB7QIDEXjV21eylvdQTCF5tM
3U3U5DsbxsyDW7pG5TykQOc83Z1F4AGUB2YyjMmsU5702RX3aBoH9J8wJ4dVoDWn
eevNXgR1WNpXsk3XOmunGIHEFSfEbZK9KAKOCAIP3CVUvKzS1rjlfpU+OS+qhrq8
EIIDSH4Twz25NHKTp/1Qq7YOeDrShkWKC5EWIXi3K85NKbJ6R7ulluDsv+alfAd5
0Y4RLKkDmrDQfBnQcMFmsgZmZ4/NfZPO/1siDsyTPIm/58w0pXKEyhQBi9pd/8PM
h8kzktldJFP5cPTSMz0hGMxUft5uFzHA4dAsuAUKo/zshpukjTYJW4Q8fykQ33tn
bqxheuLZO45rJo4jP1Nq/7g8yVXRae5JoxoYKEeciWW+ept2ygrQb/bUmoSWabQI
qX/TUzheRPB9TDBuRfQSHrxZb7EHTbB7E5GKbEEmFDsoB9vMcvg2k+OAmooNVtGO
s351Irsm2EBinlRBKIbej1am2pn2F96aVw5T1UJxlFGBPc6WgEOsWXtelwN2MOOs
7dyLMwjhEa775vXdcFwN15rX4MPOA2nGK+jpNrreHexv3r5dXSnOlESOC0sxMDgu
vLRJaJ2JnnuoDAvhaw6AOwzbwVGDHYl2ClUbKz7Iy5YwvF25khLswQ==
-----END CERTIFICATE-----

Просмотреть файл

@ -0,0 +1,40 @@
-----BEGIN CERTIFICATE-----
MIIG8zCCBNugAwIBAgICEAEwDQYJKoZIhvcNAQELBQAwgYgxCzAJBgNVBAYTAlVT
MRMwEQYDVQQIDApDYWxpZm9ybmlhMRUwEwYDVQQKDAxHaXRIdWIsIEluYy4xLDAq
BgNVBAsMI2VudGl0bGVtZW50cyBhcHAgYWNjZXB0YW5jZSB0ZXN0IENBMR8wHQYD
VQQDDBZpbnRlcm1lZGlhdGUtY2EuZ2l0aHViMB4XDTE4MDgwNDE2MDE1OFoXDTI4
MDgwMTE2MDE1OFowgYExCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlh
MRYwFAYDVQQHDA1TYW4gRnJhbmNpc2NvMRQwEgYDVQQKDAtHaXRIdWIgSW5jLjEZ
MBcGA1UECwwQRW50aXRsZW1lbnRzIEFwcDEUMBIGA1UEAwwLZ2l0aHViLmZha2Uw
ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDTMuTl+HsK08zKp4VuuxSN
BjAl2dsBkWy0cu6hdFg6x0RHVbVaYquSUSJJQ9P/YHZ/J0E0pZqCZ1DbVpm1HIhM
S4A2mFwt8URAACOMAIXU2sRcujimaqd3zlKmLa8E7g9lrgqKwnMyZfUjs+69G/ao
oLVv8np3XiJCKlSxezIEDnZjVKftb98wJzZEfvIS+Qw9/wKUt3Ou4SZQuytFoN+c
5KT4ebnxP9VFoeBexyVsus/ijCKafsqoEj8XvoApEP2FN8CpBIGxyotdLW3KIKz9
zg/t/IXtpIgp3gtiWp4WUpBX1bchULQ78HGxAq66/oY3ZZbKUuOhm2th0QsubgGc
s63djNYTcEhKMprjEO2BbGdgqkKkRlZQzX49hAMmFN632y0renArjOY3jGaVwEdF
S+eFsMzavVkwGT6XmUMn6d3e9cXTdI+gxAgqGGjZ81LLbHFtXBq2ZVkMqe4oA7Lw
SH8D+7tFFVlFzes3QFF84abCzAmMSlr2C+Q1G7PsoD4FfEfu3wfFDHI2K6bNmKoo
Mhwga96TYzJATmPOWA+wrAY41yiKr3k/F4xNWDGRKedX7RBORouZ3dAJKoDm/8kw
DmjXU7Ry3M15O2NHz2A0uAy6AWC3KOHXd9kSbuHJsBzCtTB6Nko4Sr0Pb6dy8OUg
i9DmRA7IRONenHv1jYVtMwIDAQABo4IBajCCAWYwCQYDVR0TBAIwADARBglghkgB
hvhCAQEEBAMCBkAwMwYJYIZIAYb4QgENBCYWJE9wZW5TU0wgR2VuZXJhdGVkIFNl
cnZlciBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUnxVJuZ7xgP0URnJW1d3Vk8bGTvMw
gcwGA1UdIwSBxDCBwYAUsNhZliK4oRjT1dCinkDurf0fS/OhgaSkgaEwgZ4xCzAJ
BgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1TYW4gRnJh
bmNpc2NvMRUwEwYDVQQKDAxHaXRIdWIsIEluYy4xLDAqBgNVBAsMI2VudGl0bGVt
ZW50cyBhcHAgYWNjZXB0YW5jZSB0ZXN0IENBMR0wGwYDVQQDDBRhY2NlcHRhbmNl
LWNhLmdpdGh1YoICEAAwDgYDVR0PAQH/BAQDAgWgMBMGA1UdJQQMMAoGCCsGAQUF
BwMBMA0GCSqGSIb3DQEBCwUAA4ICAQA1aUG7IlEcvSyM727yW/jXbhBLZSsbqRws
lcrGa3QtvbxjhdERDmOuEsm5nxok8UJiix//0Ew3DDF3FmiyEiM1rKkYakntwIbP
JmxLAXX2RXUqklJzvF+3CpU82XF31a34hDyoc2/DM64Ha9RiM17gSlwUfrRoOSmK
REa33T6mQWid6VljcYzFabYHdTQkXDU7TiCwKOiZHgnrMPA1W+atvSIh2JWgVJdp
w/dxxpOuE3dkL6WpntlWfSQHQToHbiyjDLhl918W9YHKQSRE2RHA3YoGE2gEdCz3
HG/4Rrfp4WFRPUe1lscnm/5x6STQekHSLl+d56f+KBKQYl78VMUaDwbFrGaOok5u
XUCyhRWsOnHVRhQWe6Y6j/ScBWuog1tKeYE18vxplREMjW9Zij6pnpuF7APaSks7
KUfv3xrqSSCDpxXFU2W27DzdWeQHKTh+efunk1r22XdxgMA+b6xUyt/zMlfxuf9C
HigcjjD7UFgw10bdV09ZjEZ43dwH+AhBVCcyf81gdiL3OOpGRW5QSSBwncyNxB8c
n7Xo1FaF2Ao3X5Bwb5nYjdIbGHOSAfVcK4iTrltjxtVhPdvKs6aguircnol867nV
WS0w/Mvt2gzbh06OCMOG2YoQvvUJuMtzKTnxLGOFNSLitcbkK5A3Y08a1gT+8bwa
9i4cSDAvaw==
-----END CERTIFICATE-----

Просмотреть файл

@ -0,0 +1,35 @@
-----BEGIN CERTIFICATE-----
MIIGCjCCA/KgAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwgZ4xCzAJBgNVBAYTAlVT
MRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1TYW4gRnJhbmNpc2NvMRUw
EwYDVQQKDAxHaXRIdWIsIEluYy4xLDAqBgNVBAsMI2VudGl0bGVtZW50cyBhcHAg
YWNjZXB0YW5jZSB0ZXN0IENBMR0wGwYDVQQDDBRhY2NlcHRhbmNlLWNhLmdpdGh1
YjAeFw0xODAzMDEyMTQ0MThaFw0zNzExMTYyMTQ0MThaMIGIMQswCQYDVQQGEwJV
UzETMBEGA1UECAwKQ2FsaWZvcm5pYTEVMBMGA1UECgwMR2l0SHViLCBJbmMuMSww
KgYDVQQLDCNlbnRpdGxlbWVudHMgYXBwIGFjY2VwdGFuY2UgdGVzdCBDQTEfMB0G
A1UEAwwWaW50ZXJtZWRpYXRlLWNhLmdpdGh1YjCCAiIwDQYJKoZIhvcNAQEBBQAD
ggIPADCCAgoCggIBAJZfDROyejD2AKheJUyAonf44Li8cAtbr6vCZ4/RyvoPiYD/
uJBBkV09/y3ldkQgHBt9zr7SE4BKjJI/w+X1bo26bD7RvRaC8gxUrT5ym5cJAXaf
1/QXoLiORxlK4F1TZKb8anFvNtS5nZ8Bzyxewm65cDUlyZJhMTBWTSs8qIXHSL0D
PaqKytnQCmtGCQYdb0qPV/aQpmlw8oW1mkdQTiJy5getBh/eDKQcC+owdl+ZvDOd
sFpcYWY5VgxdUTmnNQRRLUW55SMJJBppdxveLcMQOb43W9FBNL4pkSZ2yC+0ES/2
0FI7ydixucqeu5HPpS3eRPTkr3ATtO685LMsAAfn0AlLlnQ2fLMNZWD7bYtoNWSd
uxpZrVJhsAqTFHd/bx/aSPRdYDwoS9bIYin8uEUx7LQNX9/viO7NDcS6Kor7Lpu4
kqy7HvSSgoY6bDuGm/mexzOL9IljHac9ztuoeCDa/Gca57asu4pp5mWZnBgHfIu9
U9fxiqadTmHHYgXgEB2SXaSM0GIwy7014L3Bpsdlp/4ywTaOpxsiJntHlZLfw5Jw
LJA696xq6pQl7vkdkDm5UF2BH+dk3wuRX1MCCbim1CwGtwws4UR+NQH6A5CKfBbL
VTOLO4nqe7X7/u+s7p1McI+LPuMnfM1eu5yFblmvebNggcLpKOPea+ClqIIlAgMB
AAGjZjBkMB0GA1UdDgQWBBSw2FmWIrihGNPV0KKeQO6t/R9L8zAfBgNVHSMEGDAW
gBRBz6kdMvw+0jFsMUp2e7IetE1L6jASBgNVHRMBAf8ECDAGAQH/AgEAMA4GA1Ud
DwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAgEA3mt0BFljOxA2HuXV/vXdGBQY
ErR2vGZNvS0DMBhBBZcWaILesFeBEiHxLXlDcSisvsK2LsN6s3N8AYPY9s6f6XQ1
amSG9osfTouS2y/JqO3bbJSjL/pjz1/s1x/d9PwYPlEFeCniihAbwpQiYoyec0wh
ihQ1vDs4wQBLD+Gj+gYhnUf35OWhBjVw+iu0/oIxjdmQEQS1Qe/zimk+CpmdGf5u
rNWKDxs5TSskvCIwBdzh/hCvVuzk7fATc1pj5IaGi8I5o5070O4OJ5O2vLnKuwQw
pr7AYRGvew08xaMKVXhnBa9rNyynwb6u6vOeks8C6WQF14i+0WPPk/vcyfQZv6t6
lpD8kalzV94MbIM27HFY0dgboIhYFYJ31RGiC8lq1JYKdeBY2Z8eKRbmwrfvDiYU
CYAVkYH2QHD3a/H5fuB0JR20Tt82+NKKsH+fZO+kCMRDRpmRzG/H7Aiahs4gwjqq
29jTFg2NGYyoBfyQELuHSM/iW7reHdg/F1WqUW7AGmoAtf0Jk1PGfIJbczRAGYqS
FWh1X9nHvh51jg8arHPaRiYeLuSsjkYvnQGVhNnb+0q6M1H7tHZfKahuuUKeem4+
5l2eDeY3FlijQ6jtHOF4HsfJMlDTFLb6Adtl46Quh6zFJjkApldl6L9IuAbSffHV
Kpfjbv8qMtY2qx/pYI0=
-----END CERTIFICATE-----

Просмотреть файл

@ -0,0 +1,35 @@
-----BEGIN CERTIFICATE-----
MIIGDDCCA/SgAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwgYgxCzAJBgNVBAYTAlVT
MRMwEQYDVQQIDApDYWxpZm9ybmlhMRUwEwYDVQQKDAxHaXRIdWIsIEluYy4xLDAq
BgNVBAsMI2VudGl0bGVtZW50cyBhcHAgYWNjZXB0YW5jZSB0ZXN0IENBMR8wHQYD
VQQDDBZpbnRlcm1lZGlhdGUtY2EuZ2l0aHViMB4XDTE4MDMwMTIxNDc0N1oXDTI4
MDIyNzIxNDc0N1owgZoxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlh
MRYwFAYDVQQHDA1TYW4gRnJhbmNpc2NvMRUwEwYDVQQKDAxHaXRIdWIsIEluYy4x
LDAqBgNVBAsMI2VudGl0bGVtZW50cyBhcHAgYWNjZXB0YW5jZSB0ZXN0IENBMRkw
FwYDVQQDDBBsZGFwLXNlcnZlci5mYWtlMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
MIIBCgKCAQEAxOfyPfi1TmXKIaeTNvK8i0HTpnt1/VTYAUVJRFLvZbKvhcz6qvO9
3XVNQej+ZacGuSxh7NOKCOUGBc5K9P//Y1xAyH+FrvdP8Q73fY8yGcAWWvCAM9Z/
Hw22aPvSiiG4s1Lro4IRW2ubZcfkZAhkUTVLJCVqrXczxJ2KhqgbKdmTPa+xGhcd
tTHvX6NnKQHpYqfSH3OSabLx2YM6WYsC97OMGDFUpN3vObF6/YvgdU8qDKln7cB3
Q3B2FaBxAccZEhmUvV+fsYLhNjVPMs/VvIWK6xD7TLaLnE2O19tRWUAGl4woaeby
lwNsyqefJP0HrodnzYxvMEVNydNDKtCcYQIDAQABo4IBajCCAWYwCQYDVR0TBAIw
ADARBglghkgBhvhCAQEEBAMCBkAwMwYJYIZIAYb4QgENBCYWJE9wZW5TU0wgR2Vu
ZXJhdGVkIFNlcnZlciBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUuYHcULNnfwrZHwYk
ImOnE0CUa5wwgcwGA1UdIwSBxDCBwYAUsNhZliK4oRjT1dCinkDurf0fS/OhgaSk
gaEwgZ4xCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQH
DA1TYW4gRnJhbmNpc2NvMRUwEwYDVQQKDAxHaXRIdWIsIEluYy4xLDAqBgNVBAsM
I2VudGl0bGVtZW50cyBhcHAgYWNjZXB0YW5jZSB0ZXN0IENBMR0wGwYDVQQDDBRh
Y2NlcHRhbmNlLWNhLmdpdGh1YoICEAAwDgYDVR0PAQH/BAQDAgWgMBMGA1UdJQQM
MAoGCCsGAQUFBwMBMA0GCSqGSIb3DQEBCwUAA4ICAQBQPyaEjFKfTMYe2bSrCLt+
UOrYfFdsEVxK4rtsKwLtSpHQXfD/tF/3XV0jOU/yP/bB40leQ8AzGBnZLKPbh0P2
oaKqazBwd2aaCePUUXy831pM5v+NpRi2jX9gKjT1cAHLDjAYPt9Cd3D9IycWeand
8QWU5CzXCZrjDhDC8T7rplyO3bA2TwWnXt/BqsgKAIoGt/6EUR/YmQSL2K7ykU8Z
UAN6Kx6P3dRNkQ/5RCXx65Tum2ogXUkE/w8GWNYB21VGWMPIp1v8i8uBESg9aHRU
pQg6xOdAU1XekdFrau5JsNoYupPj125aAiKgLxvvz/xOpaQh0jQyzmlGH63i0nMv
uF2c1CQRVpjEqPW5Ok5fDQLPJQ7PP49k/5Fl+uDgAEEmq3lpF0yYFmDr8gTMZ8mf
sPahN6xZQCsIN3BlPkpuf0harHWhwyr1CTT1vSrcKdUGxeOxMPrjhZIYgDrpMAt8
B1n7BGfLJqQJ7shjOpaqCv67qqDLWcbhMMKZYbdDgoQyhT1GjFNVcIgNFgOj9vCj
9GF6eInT0LuNQEfnXJ4V6JlswFS7A6L9Us5vAgg1HmAGqQ339Ljy6Py/nN5QwUGp
cqVcWDioSZq0HSkPo753/NDTAfn/AeIS+Wn3BXHZpoXhmZplp3JL3MfP9Aww+ZnL
xRYlA4mOUC6bNM9DVzw3AA==
-----END CERTIFICATE-----

Просмотреть файл

@ -0,0 +1 @@
1000

Просмотреть файл

@ -0,0 +1,28 @@
-----BEGIN CERTIFICATE REQUEST-----
MIIExzCCAq8CAQAwgYExCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlh
MRYwFAYDVQQHDA1TYW4gRnJhbmNpc2NvMRQwEgYDVQQKDAtHaXRIdWIgSW5jLjEZ
MBcGA1UECwwQRW50aXRsZW1lbnRzIEFwcDEUMBIGA1UEAwwLZ2l0aHViLmZha2Uw
ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDTMuTl+HsK08zKp4VuuxSN
BjAl2dsBkWy0cu6hdFg6x0RHVbVaYquSUSJJQ9P/YHZ/J0E0pZqCZ1DbVpm1HIhM
S4A2mFwt8URAACOMAIXU2sRcujimaqd3zlKmLa8E7g9lrgqKwnMyZfUjs+69G/ao
oLVv8np3XiJCKlSxezIEDnZjVKftb98wJzZEfvIS+Qw9/wKUt3Ou4SZQuytFoN+c
5KT4ebnxP9VFoeBexyVsus/ijCKafsqoEj8XvoApEP2FN8CpBIGxyotdLW3KIKz9
zg/t/IXtpIgp3gtiWp4WUpBX1bchULQ78HGxAq66/oY3ZZbKUuOhm2th0QsubgGc
s63djNYTcEhKMprjEO2BbGdgqkKkRlZQzX49hAMmFN632y0renArjOY3jGaVwEdF
S+eFsMzavVkwGT6XmUMn6d3e9cXTdI+gxAgqGGjZ81LLbHFtXBq2ZVkMqe4oA7Lw
SH8D+7tFFVlFzes3QFF84abCzAmMSlr2C+Q1G7PsoD4FfEfu3wfFDHI2K6bNmKoo
Mhwga96TYzJATmPOWA+wrAY41yiKr3k/F4xNWDGRKedX7RBORouZ3dAJKoDm/8kw
DmjXU7Ry3M15O2NHz2A0uAy6AWC3KOHXd9kSbuHJsBzCtTB6Nko4Sr0Pb6dy8OUg
i9DmRA7IRONenHv1jYVtMwIDAQABoAAwDQYJKoZIhvcNAQELBQADggIBAGyN0ijX
wCXs63bG1q9LuhAxtzE3oK9jzxoLr4ObHS2hf8Ix5Vlgw8TSPam/z/P3cQxdfItS
0U8pRbmPa+Cmuv2bx9SAz9PRMGZXUklh6RF81maHgJt/EdjXIAOdSqSTuilJvTT6
jo2BDOkv0G+iInSKbBY/Q5M7a36Xy4u1WbGabd+wIkQTnNmCUPTV13DbmMkVEGhC
qq5/S/oMnBs9IbfcqOYR50tyI1T2Y7vMBVq2oKIPmqNGB7qDO9unUt+rF1JJJ++E
2SoDAJpVD/VzNOkAdWv+Br7WeIlFGAQAygU1T+dYLM3bW6m6JNhI3GdxMYl1xber
1oND/5OU8amM9b2p47ziQHhR+ZbpEbYcRFqKy236/4uCzNnAsJaAFHGQDRJ5TrIk
nRnZvcEdaUcID96qUeFhmkuhO/zcA6cXTbPXkr/QPP+C6YBPIk+UcOfrvGgchje7
VUYRI7JZD7a9EflQVTvnms2oNPqOE7GLhsfk3pLwoxVe7rC35E07YOD6thSURS7s
GligtIWNines48XQ8tDynPf2AQI4VJLHqZ8+RgSW3S45M+spBlkGTkH/LtPIjE5F
O3IZJBqaafeSbSwlahDY7gCFp/ol1BsGMhGnSK4zKEF++SdP4x+tsN4j0gDSAYPg
Y3zSxqShCe0+62u3hQGJH++uytshC/Guctfv
-----END CERTIFICATE REQUEST-----

Просмотреть файл

@ -0,0 +1,29 @@
-----BEGIN CERTIFICATE REQUEST-----
MIIE5jCCAs4CAQAwgaAxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlh
MRYwFAYDVQQHDA1TYW4gRnJhbmNpc2NvMRUwEwYDVQQKDAxHaXRIdWIsIEluYy4x
LDAqBgNVBAsMI2VudGl0bGVtZW50cyBhcHAgYWNjZXB0YW5jZSB0ZXN0IENBMR8w
HQYDVQQDDBZpbnRlcm1lZGlhdGUtY2EuZ2l0aHViMIICIjANBgkqhkiG9w0BAQEF
AAOCAg8AMIICCgKCAgEAll8NE7J6MPYAqF4lTICid/jguLxwC1uvq8Jnj9HK+g+J
gP+4kEGRXT3/LeV2RCAcG33OvtITgEqMkj/D5fVujbpsPtG9FoLyDFStPnKblwkB
dp/X9BeguI5HGUrgXVNkpvxqcW821LmdnwHPLF7CbrlwNSXJkmExMFZNKzyohcdI
vQM9qorK2dAKa0YJBh1vSo9X9pCmaXDyhbWaR1BOInLmB60GH94MpBwL6jB2X5m8
M52wWlxhZjlWDF1ROac1BFEtRbnlIwkkGml3G94twxA5vjdb0UE0vimRJnbIL7QR
L/bQUjvJ2LG5yp67kc+lLd5E9OSvcBO07rzksywAB+fQCUuWdDZ8sw1lYPtti2g1
ZJ27GlmtUmGwCpMUd39vH9pI9F1gPChL1shiKfy4RTHstA1f3++I7s0NxLoqivsu
m7iSrLse9JKChjpsO4ab+Z7HM4v0iWMdpz3O26h4INr8Zxrntqy7imnmZZmcGAd8
i71T1/GKpp1OYcdiBeAQHZJdpIzQYjDLvTXgvcGmx2Wn/jLBNo6nGyIme0eVkt/D
knAskDr3rGrqlCXu+R2QOblQXYEf52TfC5FfUwIJuKbULAa3DCzhRH41AfoDkIp8
FstVM4s7iep7tfv+76zunUxwj4s+4yd8zV67nIVuWa95s2CBwuko495r4KWogiUC
AwEAAaAAMA0GCSqGSIb3DQEBCwUAA4ICAQBPrKarbvuT7jtdlA//OgVOOxBIVuPf
99eG3khYuVtiAUdCFvDcNjfqDrxtcTyoFhlX2nj71pPVvzzt8N5K/TmXfbQ/du5v
EeoTSIf8dwOB5huymV4zrl10+MZyshth5X3d27zZh/i0A1Pxgrn/nrDyTNVCxV7x
OSTr4ihuehxuINut463YyoZUDrBZnQKmy78HpnPLDCg+g2cLPqKT2HgEfq/3mLRu
oVvbTyVYn8E0xLiPKsoCXKSPH2+aoXAss4mLMqMDzeyXG3DmS8Nx5RjVPtGxmvBQ
2GPBdEio12pctupeFznVzhxyt60aoZ+UsjJQcFvIZQJtDJm5Fy1O6hUz+JJomZ7p
6Tg9tw7VVHNMcx3Qe1fI+4aVq0ZWpRockGpclztNYo3P7CPnMV6fjMGo7vwRhSE0
+wS+hV4C0vmgTcfHVdLt6QDjYYCteH+5u68AMtpBDjGPpRhIBCnw89D91/TZijYm
Hsk90SrIQ5y0IArT/+pDdRy6I/A/qAadGyNi14DjVexsNFFH4vrkVRWX3QdcGxvX
vkMPLlv1OQ9BP47ROWMJgUK3Nc++o+hg2lc8GmlAYZ4o2daRX5Pt3qaH/rxRob7D
ZDKJLmrKoLmtckZJtofncsbum7qOeAmFszBTNs6e/Qv37VaZrMUxHWVZeZL6SLdG
8sbc6ngSu9zUyw==
-----END CERTIFICATE REQUEST-----

Просмотреть файл

@ -0,0 +1,18 @@
-----BEGIN CERTIFICATE REQUEST-----
MIIC4DCCAcgCAQAwgZoxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlh
MRYwFAYDVQQHDA1TYW4gRnJhbmNpc2NvMRUwEwYDVQQKDAxHaXRIdWIsIEluYy4x
LDAqBgNVBAsMI2VudGl0bGVtZW50cyBhcHAgYWNjZXB0YW5jZSB0ZXN0IENBMRkw
FwYDVQQDDBBsZGFwLXNlcnZlci5mYWtlMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
MIIBCgKCAQEAxOfyPfi1TmXKIaeTNvK8i0HTpnt1/VTYAUVJRFLvZbKvhcz6qvO9
3XVNQej+ZacGuSxh7NOKCOUGBc5K9P//Y1xAyH+FrvdP8Q73fY8yGcAWWvCAM9Z/
Hw22aPvSiiG4s1Lro4IRW2ubZcfkZAhkUTVLJCVqrXczxJ2KhqgbKdmTPa+xGhcd
tTHvX6NnKQHpYqfSH3OSabLx2YM6WYsC97OMGDFUpN3vObF6/YvgdU8qDKln7cB3
Q3B2FaBxAccZEhmUvV+fsYLhNjVPMs/VvIWK6xD7TLaLnE2O19tRWUAGl4woaeby
lwNsyqefJP0HrodnzYxvMEVNydNDKtCcYQIDAQABoAAwDQYJKoZIhvcNAQELBQAD
ggEBAJGIcuQvJw6PANXkpVYJoRd09A37MLUPwIW2QJUtqezjwxa6y6YO3e/Y0f+3
5ILXsH/uUIq6YGs4tjS3K0Dob3TOksDNef++oTizmbFqCJt18a2dg395p//QT1u0
WAt5eNb7dNcENNu5wwON6vf4DWq2u5H494bTVCh6WiDmK9sdDwx6tufX2FQUz98s
xA1SPguRAqBBwDwhfX9gGi0vAi2TXVyKjoU7Ks7kr8KxJsF4YQIPSBXDPzmfZmjO
WLzdJhrIBKua2E5F1rPZdRRXIEdEw/SvOFfrC4H09sAH590hl1j2G4MSHdikITvf
OxmZPzUIcr4VSWDh+UE9yEkQp0c=
-----END CERTIFICATE REQUEST-----

Просмотреть файл

@ -0,0 +1,2 @@
V 280227214747Z 1000 unknown /C=US/ST=California/L=San Francisco/O=GitHub, Inc./OU=entitlements app acceptance test CA/CN=ldap-server.fake
V 280801160158Z 1001 unknown /C=US/ST=California/L=San Francisco/O=GitHub Inc./OU=Entitlements App/CN=github.fake

Просмотреть файл

@ -0,0 +1 @@
unique_subject = yes

Просмотреть файл

@ -0,0 +1 @@
unique_subject = yes

Просмотреть файл

@ -0,0 +1 @@
V 280227214747Z 1000 unknown /C=US/ST=California/L=San Francisco/O=GitHub, Inc./OU=entitlements app acceptance test CA/CN=ldap-server.fake

Просмотреть файл

@ -0,0 +1,35 @@
-----BEGIN CERTIFICATE-----
MIIGDDCCA/SgAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwgYgxCzAJBgNVBAYTAlVT
MRMwEQYDVQQIDApDYWxpZm9ybmlhMRUwEwYDVQQKDAxHaXRIdWIsIEluYy4xLDAq
BgNVBAsMI2VudGl0bGVtZW50cyBhcHAgYWNjZXB0YW5jZSB0ZXN0IENBMR8wHQYD
VQQDDBZpbnRlcm1lZGlhdGUtY2EuZ2l0aHViMB4XDTE4MDMwMTIxNDc0N1oXDTI4
MDIyNzIxNDc0N1owgZoxCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlh
MRYwFAYDVQQHDA1TYW4gRnJhbmNpc2NvMRUwEwYDVQQKDAxHaXRIdWIsIEluYy4x
LDAqBgNVBAsMI2VudGl0bGVtZW50cyBhcHAgYWNjZXB0YW5jZSB0ZXN0IENBMRkw
FwYDVQQDDBBsZGFwLXNlcnZlci5mYWtlMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8A
MIIBCgKCAQEAxOfyPfi1TmXKIaeTNvK8i0HTpnt1/VTYAUVJRFLvZbKvhcz6qvO9
3XVNQej+ZacGuSxh7NOKCOUGBc5K9P//Y1xAyH+FrvdP8Q73fY8yGcAWWvCAM9Z/
Hw22aPvSiiG4s1Lro4IRW2ubZcfkZAhkUTVLJCVqrXczxJ2KhqgbKdmTPa+xGhcd
tTHvX6NnKQHpYqfSH3OSabLx2YM6WYsC97OMGDFUpN3vObF6/YvgdU8qDKln7cB3
Q3B2FaBxAccZEhmUvV+fsYLhNjVPMs/VvIWK6xD7TLaLnE2O19tRWUAGl4woaeby
lwNsyqefJP0HrodnzYxvMEVNydNDKtCcYQIDAQABo4IBajCCAWYwCQYDVR0TBAIw
ADARBglghkgBhvhCAQEEBAMCBkAwMwYJYIZIAYb4QgENBCYWJE9wZW5TU0wgR2Vu
ZXJhdGVkIFNlcnZlciBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUuYHcULNnfwrZHwYk
ImOnE0CUa5wwgcwGA1UdIwSBxDCBwYAUsNhZliK4oRjT1dCinkDurf0fS/OhgaSk
gaEwgZ4xCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQH
DA1TYW4gRnJhbmNpc2NvMRUwEwYDVQQKDAxHaXRIdWIsIEluYy4xLDAqBgNVBAsM
I2VudGl0bGVtZW50cyBhcHAgYWNjZXB0YW5jZSB0ZXN0IENBMR0wGwYDVQQDDBRh
Y2NlcHRhbmNlLWNhLmdpdGh1YoICEAAwDgYDVR0PAQH/BAQDAgWgMBMGA1UdJQQM
MAoGCCsGAQUFBwMBMA0GCSqGSIb3DQEBCwUAA4ICAQBQPyaEjFKfTMYe2bSrCLt+
UOrYfFdsEVxK4rtsKwLtSpHQXfD/tF/3XV0jOU/yP/bB40leQ8AzGBnZLKPbh0P2
oaKqazBwd2aaCePUUXy831pM5v+NpRi2jX9gKjT1cAHLDjAYPt9Cd3D9IycWeand
8QWU5CzXCZrjDhDC8T7rplyO3bA2TwWnXt/BqsgKAIoGt/6EUR/YmQSL2K7ykU8Z
UAN6Kx6P3dRNkQ/5RCXx65Tum2ogXUkE/w8GWNYB21VGWMPIp1v8i8uBESg9aHRU
pQg6xOdAU1XekdFrau5JsNoYupPj125aAiKgLxvvz/xOpaQh0jQyzmlGH63i0nMv
uF2c1CQRVpjEqPW5Ok5fDQLPJQ7PP49k/5Fl+uDgAEEmq3lpF0yYFmDr8gTMZ8mf
sPahN6xZQCsIN3BlPkpuf0harHWhwyr1CTT1vSrcKdUGxeOxMPrjhZIYgDrpMAt8
B1n7BGfLJqQJ7shjOpaqCv67qqDLWcbhMMKZYbdDgoQyhT1GjFNVcIgNFgOj9vCj
9GF6eInT0LuNQEfnXJ4V6JlswFS7A6L9Us5vAgg1HmAGqQ339Ljy6Py/nN5QwUGp
cqVcWDioSZq0HSkPo753/NDTAfn/AeIS+Wn3BXHZpoXhmZplp3JL3MfP9Aww+ZnL
xRYlA4mOUC6bNM9DVzw3AA==
-----END CERTIFICATE-----

Просмотреть файл

@ -0,0 +1,40 @@
-----BEGIN CERTIFICATE-----
MIIG8zCCBNugAwIBAgICEAEwDQYJKoZIhvcNAQELBQAwgYgxCzAJBgNVBAYTAlVT
MRMwEQYDVQQIDApDYWxpZm9ybmlhMRUwEwYDVQQKDAxHaXRIdWIsIEluYy4xLDAq
BgNVBAsMI2VudGl0bGVtZW50cyBhcHAgYWNjZXB0YW5jZSB0ZXN0IENBMR8wHQYD
VQQDDBZpbnRlcm1lZGlhdGUtY2EuZ2l0aHViMB4XDTE4MDgwNDE2MDE1OFoXDTI4
MDgwMTE2MDE1OFowgYExCzAJBgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlh
MRYwFAYDVQQHDA1TYW4gRnJhbmNpc2NvMRQwEgYDVQQKDAtHaXRIdWIgSW5jLjEZ
MBcGA1UECwwQRW50aXRsZW1lbnRzIEFwcDEUMBIGA1UEAwwLZ2l0aHViLmZha2Uw
ggIiMA0GCSqGSIb3DQEBAQUAA4ICDwAwggIKAoICAQDTMuTl+HsK08zKp4VuuxSN
BjAl2dsBkWy0cu6hdFg6x0RHVbVaYquSUSJJQ9P/YHZ/J0E0pZqCZ1DbVpm1HIhM
S4A2mFwt8URAACOMAIXU2sRcujimaqd3zlKmLa8E7g9lrgqKwnMyZfUjs+69G/ao
oLVv8np3XiJCKlSxezIEDnZjVKftb98wJzZEfvIS+Qw9/wKUt3Ou4SZQuytFoN+c
5KT4ebnxP9VFoeBexyVsus/ijCKafsqoEj8XvoApEP2FN8CpBIGxyotdLW3KIKz9
zg/t/IXtpIgp3gtiWp4WUpBX1bchULQ78HGxAq66/oY3ZZbKUuOhm2th0QsubgGc
s63djNYTcEhKMprjEO2BbGdgqkKkRlZQzX49hAMmFN632y0renArjOY3jGaVwEdF
S+eFsMzavVkwGT6XmUMn6d3e9cXTdI+gxAgqGGjZ81LLbHFtXBq2ZVkMqe4oA7Lw
SH8D+7tFFVlFzes3QFF84abCzAmMSlr2C+Q1G7PsoD4FfEfu3wfFDHI2K6bNmKoo
Mhwga96TYzJATmPOWA+wrAY41yiKr3k/F4xNWDGRKedX7RBORouZ3dAJKoDm/8kw
DmjXU7Ry3M15O2NHz2A0uAy6AWC3KOHXd9kSbuHJsBzCtTB6Nko4Sr0Pb6dy8OUg
i9DmRA7IRONenHv1jYVtMwIDAQABo4IBajCCAWYwCQYDVR0TBAIwADARBglghkgB
hvhCAQEEBAMCBkAwMwYJYIZIAYb4QgENBCYWJE9wZW5TU0wgR2VuZXJhdGVkIFNl
cnZlciBDZXJ0aWZpY2F0ZTAdBgNVHQ4EFgQUnxVJuZ7xgP0URnJW1d3Vk8bGTvMw
gcwGA1UdIwSBxDCBwYAUsNhZliK4oRjT1dCinkDurf0fS/OhgaSkgaEwgZ4xCzAJ
BgNVBAYTAlVTMRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1TYW4gRnJh
bmNpc2NvMRUwEwYDVQQKDAxHaXRIdWIsIEluYy4xLDAqBgNVBAsMI2VudGl0bGVt
ZW50cyBhcHAgYWNjZXB0YW5jZSB0ZXN0IENBMR0wGwYDVQQDDBRhY2NlcHRhbmNl
LWNhLmdpdGh1YoICEAAwDgYDVR0PAQH/BAQDAgWgMBMGA1UdJQQMMAoGCCsGAQUF
BwMBMA0GCSqGSIb3DQEBCwUAA4ICAQA1aUG7IlEcvSyM727yW/jXbhBLZSsbqRws
lcrGa3QtvbxjhdERDmOuEsm5nxok8UJiix//0Ew3DDF3FmiyEiM1rKkYakntwIbP
JmxLAXX2RXUqklJzvF+3CpU82XF31a34hDyoc2/DM64Ha9RiM17gSlwUfrRoOSmK
REa33T6mQWid6VljcYzFabYHdTQkXDU7TiCwKOiZHgnrMPA1W+atvSIh2JWgVJdp
w/dxxpOuE3dkL6WpntlWfSQHQToHbiyjDLhl918W9YHKQSRE2RHA3YoGE2gEdCz3
HG/4Rrfp4WFRPUe1lscnm/5x6STQekHSLl+d56f+KBKQYl78VMUaDwbFrGaOok5u
XUCyhRWsOnHVRhQWe6Y6j/ScBWuog1tKeYE18vxplREMjW9Zij6pnpuF7APaSks7
KUfv3xrqSSCDpxXFU2W27DzdWeQHKTh+efunk1r22XdxgMA+b6xUyt/zMlfxuf9C
HigcjjD7UFgw10bdV09ZjEZ43dwH+AhBVCcyf81gdiL3OOpGRW5QSSBwncyNxB8c
n7Xo1FaF2Ao3X5Bwb5nYjdIbGHOSAfVcK4iTrltjxtVhPdvKs6aguircnol867nV
WS0w/Mvt2gzbh06OCMOG2YoQvvUJuMtzKTnxLGOFNSLitcbkK5A3Y08a1gT+8bwa
9i4cSDAvaw==
-----END CERTIFICATE-----

Просмотреть файл

@ -0,0 +1,132 @@
# OpenSSL root CA configuration file.
# https://jamielinux.com/docs/openssl-certificate-authority/_downloads/root-config.txt
[ ca ]
# `man ca`
default_ca = CA_default
[ CA_default ]
# Directory and file locations.
dir = ./intermediate
certs = $dir/certs
crl_dir = $dir/crl
new_certs_dir = $dir/newcerts
database = $dir/index.txt
serial = $dir/serial
RANDFILE = $dir/private/.rand
# The root key and root certificate.
private_key = $dir/private/intermediate.key.pem
certificate = $dir/certs/intermediate.cert.pem
# For certificate revocation lists.
crlnumber = $dir/crlnumber
crl = $dir/crl/ca.crl.pem
crl_extensions = crl_ext
default_crl_days = 30
# SHA-1 is deprecated, so use SHA-2 instead.
default_md = sha256
name_opt = ca_default
cert_opt = ca_default
default_days = 3650
preserve = no
policy = policy_loose
[ policy_strict ]
# The root CA should only sign intermediate certificates that match.
# See the POLICY FORMAT section of `man ca`.
countryName = match
stateOrProvinceName = match
organizationName = match
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
[ policy_loose ]
# Allow the intermediate CA to sign a more diverse range of certificates.
# See the POLICY FORMAT section of the `ca` man page.
countryName = optional
stateOrProvinceName = optional
localityName = optional
organizationName = optional
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
[ req ]
# Options for the `req` tool (`man req`).
default_bits = 2048
distinguished_name = req_distinguished_name
string_mask = utf8only
# SHA-1 is deprecated, so use SHA-2 instead.
default_md = sha256
# Extension to add when the -x509 option is used.
x509_extensions = v3_ca
[ req_distinguished_name ]
# See <https://en.wikipedia.org/wiki/Certificate_signing_request>.
countryName = Country Name (2 letter code)
stateOrProvinceName = State or Province Name
localityName = Locality Name
0.organizationName = Organization Name
organizationalUnitName = Organizational Unit Name
commonName = Common Name
emailAddress = Email Address
# Optionally, specify some defaults.
countryName_default = GB
stateOrProvinceName_default = England
localityName_default =
0.organizationName_default = Alice Ltd
organizationalUnitName_default =
emailAddress_default =
[ v3_ca ]
# Extensions for a typical CA (`man x509v3_config`).
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:true
keyUsage = critical, digitalSignature, cRLSign, keyCertSign
[ v3_intermediate_ca ]
# Extensions for a typical intermediate CA (`man x509v3_config`).
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:true, pathlen:0
keyUsage = critical, digitalSignature, cRLSign, keyCertSign
[ usr_cert ]
# Extensions for client certificates (`man x509v3_config`).
basicConstraints = CA:FALSE
nsCertType = client, email
nsComment = "OpenSSL Generated Client Certificate"
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = clientAuth, emailProtection
[ server_cert ]
# Extensions for server certificates (`man x509v3_config`).
basicConstraints = CA:FALSE
nsCertType = server
nsComment = "OpenSSL Generated Server Certificate"
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer:always
keyUsage = critical, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
[ crl_ext ]
# Extension for CRLs (`man x509v3_config`).
authorityKeyIdentifier=keyid:always
[ ocsp ]
# Extension for OCSP signing certificates (`man ocsp`).
basicConstraints = CA:FALSE
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
keyUsage = critical, digitalSignature
extendedKeyUsage = critical, OCSPSigning

Просмотреть файл

@ -0,0 +1,54 @@
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-256-CBC,CFB07176D5D8B7B07E48974FEB8AD84C
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
-----END RSA PRIVATE KEY-----

Просмотреть файл

@ -0,0 +1,27 @@
-----BEGIN RSA PRIVATE KEY-----
MIIEpAIBAAKCAQEAxOfyPfi1TmXKIaeTNvK8i0HTpnt1/VTYAUVJRFLvZbKvhcz6
qvO93XVNQej+ZacGuSxh7NOKCOUGBc5K9P//Y1xAyH+FrvdP8Q73fY8yGcAWWvCA
M9Z/Hw22aPvSiiG4s1Lro4IRW2ubZcfkZAhkUTVLJCVqrXczxJ2KhqgbKdmTPa+x
GhcdtTHvX6NnKQHpYqfSH3OSabLx2YM6WYsC97OMGDFUpN3vObF6/YvgdU8qDKln
7cB3Q3B2FaBxAccZEhmUvV+fsYLhNjVPMs/VvIWK6xD7TLaLnE2O19tRWUAGl4wo
aebylwNsyqefJP0HrodnzYxvMEVNydNDKtCcYQIDAQABAoIBAQC1jAnsm4hHHVDN
0NzJ9+phFzNWt1RlW7nBCinwZes2QBbXbdPclNkE++dckr8j6GkpiENNgQkvBEKW
TcsMs4+8A83zTqhqVroNTzhfOwz9cv7pn/8ETItujU0W5MAM/eR26kg6vGzWdpOT
t0bb+GTN/y4lyJ3gDBzd9kdHum05GjTxeMbj38xJmsj6mdp8j9Q4RUC4v6kaNV/n
jkHwtD90B/Ke1XLl8WozSaPWrh0DxSQ2TNB9uGIikRR10a5/dQhzER7O574slaPk
ybnOyoFnKzWC3aeBlibZ62Rnwy89UPr/dfzyOGkZEvQBzxtVIRUSVFnyD3uuWav4
EAUKQ4gBAoGBAOmbcs4zWDRt+wxdjQIy+LAIuT6ptd3+phvLBB2cbRCNxo4FwmG/
uacCTJr4kvvUp87YR/mWhpH4mMVskOBlrwl5yNKOt9Ym/9xT+lPoMf7nrH1Whp9H
bvvw4AWCT7yA7qp7lH+VRmI3qAD9i7TJa9e6fJ6dA/OHu1S8Cby9eZ4hAoGBANfH
4KLFxe5CP6zjMLQiS4hqVZLLda6l/Q3boWsp5YbV3IJVOEJJ0xYBOY4CVCon5DLw
A3eTCjEIAiQqMHPkobxYILCgHFq0WX1FT3ryvzkk+jb3wyRMkSVWdNoPC3Xupfbq
MfrGbbxFSwDzEaqYUay72pJSuJzQrPDdkvggBLZBAoGBAOcGycItOwUW41l2R1au
bA1Dg1f6ZJb4GPSRkS9rnNzrKTsZbQRYpNUKzBHS1SHiTFaexIeMGufPb96HILwb
M8DuRPIfHKXYid8u2fkTQCZ0nbySzq5E6fiVXid0mUC2TdIiR1jpmuLVYfwgw4J2
VIXTsxz18YttZ5FEKWkUBWuhAoGAOmR9lq7chEBrSNbmTCjntc/IvoPOoeeLVl+0
C/L3iQiAtshnBBFETTUhpRteOVY4O8yVs5sX6/LV2YGNQR+C4RwcJI//fFBH002Z
V5UvSECIca2UolMSCD+gOY5OtKhTQ0FXKxzdf1BlHqmogzjbCVqAqI44JT+XPUtI
xVqsy8ECgYB2IHRozu2VK/N4myWe6X0MbbMiQ0WVv71sOVa/Eb/WQOqpo89o3tI8
51gunM2hJZkkcdau76+LdMXs9cyUY5VYeYPIGFz6JAjp+H9P0LuhxaI2pppPQ6t9
tMorvd5QK4u3xlJVS10OLTAlRU1xsRTtRqb9KglKWw+xLAvguwTvlg==
-----END RSA PRIVATE KEY-----

Просмотреть файл

@ -0,0 +1,30 @@
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-256-CBC,B87F38A2BC95F7921446E32017040B8C
7v6YRnTkFRf2xFSSiSt/MYghO6S+MtiuJ4zmYiww1N/nb+B9lj/elxAwvTy6c8vM
e0hNOhOmzwWrOruTwTfpgKiq75ZA915t6c5DrP8ZpKAy+lAKeWFCl5Tpv/DGvwYv
id15yGwWb6mmhEYKjR83uM2S8enhWQb2l2jokols+7AEMAdnTafM+fbSKs0GeXrX
0og8tEqBC7Eax8REmVpVeg3tLwXeRB8RJl7KsLk2Y8kUsUs0RAl8WRsEazhGEuJv
rFbsd0XjcRDSXJxnGEPjrscpc5nxE3lOgbI5xWWvBNZoFn0YF+qDuzyIbpM0I6e0
lYnphYiEoGas+BjHmF5cGKa7fHuF68R4phxcI81XfDJXGj4R+eNSJOqkMFG2CvuH
waqQRLgqE3xhewV2YY/FXJpFwFtlYz53yrAAlLFfyM56psTEyy2/zjazzV2yOVeh
3B791tLk0sIPQ4p9W36PFlvTqP3Eu7ZNHAD7X7ElluhuRLa5yuAhP5tACqRis/qu
uB7OJ0iwH2eNoQO6Mkta/KVTek51ZDTN/cW+fyovJIEGS7hqsGzTtQ2ZLksrROIq
nBPaiUaHP0Do4FBBgN4ebBSmoq+xdlZGJO+rPp9O2UYZx9LeKqh/ibCCwru01Pnb
c+OYEUU3pMKN6NmWRfjw32IKaimv8IM+d7q0I18w2ZoSVE2mAorPqFi7009bl2XD
WUL7LO4N7cHDeXtWWDEw4K/AQzb/0hCpEjpTnMPDBPGZmFxxWza6zTIEYFAcyURa
tKPD4STYXvYrRi2cIpXzAsxxDK+Mfr/+GZMaQQD4DbdO9sTgvWCRwY8mvGkdNTUp
Do+xgLy3argP3iMKgAMLXDzN1tu3/obKCp/JTTrp/DEtR/Sd8kNr2+xQ7IydezZs
6yLps7l89g/M2Apo4hEGEX3K+l+2dfmogv6zCmJQHIE1llJCXkdpvtuuI6eVP8U4
ZNKPHQRJ/jJJHhizI2e2gfdbuWSdizNKOygVT9/Rk0RO846EqHBoEL+pavEthzq6
vMAWqD/TN8KrLcnl98Q2d1myMjeyd49eVZ7trNLregk92qu5i7Twx3WsOArhV0Ke
TybvGaoGmnA53MA3xKUaW8ImqSOMCH0sOtLA/5y7HBnPZtrDRP40Xz0hzozz2XgT
qHt1hsqeLnBLvSzgkZDmHfDzUu/ssWnO03SmS51/umTFeDH5Sdoivo7mAhlobL4G
moT4CPk1fVIWGF+c3b7MHbWVIW1FZbi2mcUqYyziR0kElzPe8X40+3Io0xccB6Ly
tHA+oVm8u96l+K472ndWDsA3ggTs5GomVX3LIbFZl0veXl/2SGTBaCId9QaPPdP0
uV38w4dndSSw7ZX76gPSlcxFEi383WSWobhgv7qdMyUe1G1Q+s/2U3O/uvZQO410
BzJiz1XcPxCzHuH3TN7F+ZaHliB+oIM+eKUyNxTahZtnoWxCR7zOw9epxPoGHyWt
eCzjDHxLpDas24z48Yi6YJuZwGxKrOB4af0IysmsePorDv9dv10NTnZ7TQepy/6P
a/F83vqymcxO0HgKBVBYwlXBsg5OXEFXcnfVpl91vMlUQidvW4Q7IpdrctrgRUAT
-----END RSA PRIVATE KEY-----

Просмотреть файл

@ -0,0 +1 @@
1002

Просмотреть файл

@ -0,0 +1 @@
1001

Просмотреть файл

@ -0,0 +1,35 @@
-----BEGIN CERTIFICATE-----
MIIGCjCCA/KgAwIBAgICEAAwDQYJKoZIhvcNAQELBQAwgZ4xCzAJBgNVBAYTAlVT
MRMwEQYDVQQIDApDYWxpZm9ybmlhMRYwFAYDVQQHDA1TYW4gRnJhbmNpc2NvMRUw
EwYDVQQKDAxHaXRIdWIsIEluYy4xLDAqBgNVBAsMI2VudGl0bGVtZW50cyBhcHAg
YWNjZXB0YW5jZSB0ZXN0IENBMR0wGwYDVQQDDBRhY2NlcHRhbmNlLWNhLmdpdGh1
YjAeFw0xODAzMDEyMTQ0MThaFw0zNzExMTYyMTQ0MThaMIGIMQswCQYDVQQGEwJV
UzETMBEGA1UECAwKQ2FsaWZvcm5pYTEVMBMGA1UECgwMR2l0SHViLCBJbmMuMSww
KgYDVQQLDCNlbnRpdGxlbWVudHMgYXBwIGFjY2VwdGFuY2UgdGVzdCBDQTEfMB0G
A1UEAwwWaW50ZXJtZWRpYXRlLWNhLmdpdGh1YjCCAiIwDQYJKoZIhvcNAQEBBQAD
ggIPADCCAgoCggIBAJZfDROyejD2AKheJUyAonf44Li8cAtbr6vCZ4/RyvoPiYD/
uJBBkV09/y3ldkQgHBt9zr7SE4BKjJI/w+X1bo26bD7RvRaC8gxUrT5ym5cJAXaf
1/QXoLiORxlK4F1TZKb8anFvNtS5nZ8Bzyxewm65cDUlyZJhMTBWTSs8qIXHSL0D
PaqKytnQCmtGCQYdb0qPV/aQpmlw8oW1mkdQTiJy5getBh/eDKQcC+owdl+ZvDOd
sFpcYWY5VgxdUTmnNQRRLUW55SMJJBppdxveLcMQOb43W9FBNL4pkSZ2yC+0ES/2
0FI7ydixucqeu5HPpS3eRPTkr3ATtO685LMsAAfn0AlLlnQ2fLMNZWD7bYtoNWSd
uxpZrVJhsAqTFHd/bx/aSPRdYDwoS9bIYin8uEUx7LQNX9/viO7NDcS6Kor7Lpu4
kqy7HvSSgoY6bDuGm/mexzOL9IljHac9ztuoeCDa/Gca57asu4pp5mWZnBgHfIu9
U9fxiqadTmHHYgXgEB2SXaSM0GIwy7014L3Bpsdlp/4ywTaOpxsiJntHlZLfw5Jw
LJA696xq6pQl7vkdkDm5UF2BH+dk3wuRX1MCCbim1CwGtwws4UR+NQH6A5CKfBbL
VTOLO4nqe7X7/u+s7p1McI+LPuMnfM1eu5yFblmvebNggcLpKOPea+ClqIIlAgMB
AAGjZjBkMB0GA1UdDgQWBBSw2FmWIrihGNPV0KKeQO6t/R9L8zAfBgNVHSMEGDAW
gBRBz6kdMvw+0jFsMUp2e7IetE1L6jASBgNVHRMBAf8ECDAGAQH/AgEAMA4GA1Ud
DwEB/wQEAwIBhjANBgkqhkiG9w0BAQsFAAOCAgEA3mt0BFljOxA2HuXV/vXdGBQY
ErR2vGZNvS0DMBhBBZcWaILesFeBEiHxLXlDcSisvsK2LsN6s3N8AYPY9s6f6XQ1
amSG9osfTouS2y/JqO3bbJSjL/pjz1/s1x/d9PwYPlEFeCniihAbwpQiYoyec0wh
ihQ1vDs4wQBLD+Gj+gYhnUf35OWhBjVw+iu0/oIxjdmQEQS1Qe/zimk+CpmdGf5u
rNWKDxs5TSskvCIwBdzh/hCvVuzk7fATc1pj5IaGi8I5o5070O4OJ5O2vLnKuwQw
pr7AYRGvew08xaMKVXhnBa9rNyynwb6u6vOeks8C6WQF14i+0WPPk/vcyfQZv6t6
lpD8kalzV94MbIM27HFY0dgboIhYFYJ31RGiC8lq1JYKdeBY2Z8eKRbmwrfvDiYU
CYAVkYH2QHD3a/H5fuB0JR20Tt82+NKKsH+fZO+kCMRDRpmRzG/H7Aiahs4gwjqq
29jTFg2NGYyoBfyQELuHSM/iW7reHdg/F1WqUW7AGmoAtf0Jk1PGfIJbczRAGYqS
FWh1X9nHvh51jg8arHPaRiYeLuSsjkYvnQGVhNnb+0q6M1H7tHZfKahuuUKeem4+
5l2eDeY3FlijQ6jtHOF4HsfJMlDTFLb6Adtl46Quh6zFJjkApldl6L9IuAbSffHV
Kpfjbv8qMtY2qx/pYI0=
-----END CERTIFICATE-----

Просмотреть файл

@ -0,0 +1,132 @@
# OpenSSL root CA configuration file.
# https://jamielinux.com/docs/openssl-certificate-authority/_downloads/root-config.txt
[ ca ]
# `man ca`
default_ca = CA_default
[ CA_default ]
# Directory and file locations.
dir = .
certs = $dir/certs
crl_dir = $dir/crl
new_certs_dir = $dir/newcerts
database = $dir/index.txt
serial = $dir/serial
RANDFILE = $dir/private/.rand
# The root key and root certificate.
private_key = $dir/private/ca.key.pem
certificate = $dir/certs/ca.cert.pem
# For certificate revocation lists.
crlnumber = $dir/crlnumber
crl = $dir/crl/ca.crl.pem
crl_extensions = crl_ext
default_crl_days = 30
# SHA-1 is deprecated, so use SHA-2 instead.
default_md = sha256
name_opt = ca_default
cert_opt = ca_default
default_days = 3650
preserve = no
policy = policy_strict
[ policy_strict ]
# The root CA should only sign intermediate certificates that match.
# See the POLICY FORMAT section of `man ca`.
countryName = match
stateOrProvinceName = match
organizationName = match
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
[ policy_loose ]
# Allow the intermediate CA to sign a more diverse range of certificates.
# See the POLICY FORMAT section of the `ca` man page.
countryName = optional
stateOrProvinceName = optional
localityName = optional
organizationName = optional
organizationalUnitName = optional
commonName = supplied
emailAddress = optional
[ req ]
# Options for the `req` tool (`man req`).
default_bits = 2048
distinguished_name = req_distinguished_name
string_mask = utf8only
# SHA-1 is deprecated, so use SHA-2 instead.
default_md = sha256
# Extension to add when the -x509 option is used.
x509_extensions = v3_ca
[ req_distinguished_name ]
# See <https://en.wikipedia.org/wiki/Certificate_signing_request>.
countryName = Country Name (2 letter code)
stateOrProvinceName = State or Province Name
localityName = Locality Name
0.organizationName = Organization Name
organizationalUnitName = Organizational Unit Name
commonName = Common Name
emailAddress = Email Address
# Optionally, specify some defaults.
countryName_default = GB
stateOrProvinceName_default = England
localityName_default =
0.organizationName_default = Alice Ltd
organizationalUnitName_default =
emailAddress_default =
[ v3_ca ]
# Extensions for a typical CA (`man x509v3_config`).
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:true
keyUsage = critical, digitalSignature, cRLSign, keyCertSign
[ v3_intermediate_ca ]
# Extensions for a typical intermediate CA (`man x509v3_config`).
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid:always,issuer
basicConstraints = critical, CA:true, pathlen:0
keyUsage = critical, digitalSignature, cRLSign, keyCertSign
[ usr_cert ]
# Extensions for client certificates (`man x509v3_config`).
basicConstraints = CA:FALSE
nsCertType = client, email
nsComment = "OpenSSL Generated Client Certificate"
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
keyUsage = critical, nonRepudiation, digitalSignature, keyEncipherment
extendedKeyUsage = clientAuth, emailProtection
[ server_cert ]
# Extensions for server certificates (`man x509v3_config`).
basicConstraints = CA:FALSE
nsCertType = server
nsComment = "OpenSSL Generated Server Certificate"
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer:always
keyUsage = critical, digitalSignature, keyEncipherment
extendedKeyUsage = serverAuth
[ crl_ext ]
# Extension for CRLs (`man x509v3_config`).
authorityKeyIdentifier=keyid:always
[ ocsp ]
# Extension for OCSP signing certificates (`man ocsp`).
basicConstraints = CA:FALSE
subjectKeyIdentifier = hash
authorityKeyIdentifier = keyid,issuer
keyUsage = critical, digitalSignature
extendedKeyUsage = critical, OCSPSigning

Просмотреть файл

@ -0,0 +1,54 @@
-----BEGIN RSA PRIVATE KEY-----
Proc-Type: 4,ENCRYPTED
DEK-Info: AES-256-CBC,E318106249072FADE86EF6CF5D191E4B
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
-----END RSA PRIVATE KEY-----

Просмотреть файл

@ -0,0 +1 @@
1001

Просмотреть файл

@ -0,0 +1 @@
1000

Просмотреть файл

@ -0,0 +1,41 @@
version: '2'
networks:
ldap-network:
internal: true
services:
entitlements-gitrepo-auditor-plugin:
build:
context: "${DIR}"
dockerfile: "spec/acceptance/Dockerfile.entitlements-gitrepo-auditor-plugin"
networks:
ldap-network:
aliases:
- entitlements-github-plugin.fake
volumes:
- "${DIR}/spec/acceptance:/acceptance:ro"
- "${DIR}/vendor/container-gems:/data/entitlements/vendor/gems:rw"
git-server:
entrypoint: /acceptance/git-server/run-server.sh
image: jkarlos/git-server-docker
networks:
ldap-network:
aliases:
- git-server.fake
ports:
- "127.0.0.1:22:22"
volumes:
- "${DIR}/spec/acceptance:/acceptance:ro"
- "${DIR}/spec/acceptance/git-server/keys:/git-server/keys:ro"
ldap-server:
entrypoint: /acceptance/ldap-server/run-server.sh
image: osixia/openldap:1.2.2
networks:
ldap-network:
aliases:
- ldap-server.fake
ports:
- "127.0.0.1:636:636"
volumes:
- "${DIR}/spec/acceptance:/acceptance:ro"

Просмотреть файл

Просмотреть файл

@ -0,0 +1,50 @@
<%-
require "/data/entitlements/lib/entitlements/auditor/gitrepo"
require "/data/entitlements/lib/entitlements/util/gitrepo"
-%>
---
backends:
dockerized-ldap:
ldap_binddn: <%= ENV["LDAP_BINDDN"] %>
ldap_bindpw: <%= ENV["LDAP_BINDPW"] %>
ldap_uri: <%= ENV["LDAP_URI"] %>
person_dn_format: uid=%KEY%,ou=People,dc=kittens,dc=net
type: ldap
configuration_path: ./ldap-config
auditors:
- auditor_class: GitRepo
checkout_directory: <%= ENV["GIT_REPO_CHECKOUT_DIRECTORY"] %>
commit_message: gitrepo-auditor
github_override: git@git-server.fake:/git-server/
git_name: Entitlements Acceptance Test
git_email: entitlements-acceptance-test@noreply.github.com
person_dn_format: uid=%KEY%,ou=People,dc=kittens,dc=net
repo: repos/entitlements-audit
sshkey: |
LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcEFJQkFBS0NBUUVBMzVXUmNrWHRWemd5TFJCN080Mk00b0tVT1A5STBhV0tBVkpSbXhnTmZaMDRBWk8xCmdha0c4RWlvSktldHNaUFhVdzhVZkYyTzk5cjFiQ2dZUHREejVhZ0FmeDRBSS9IOGJBTlN3Z0hpWW9tdVd5VTIKMHZEaitBQndtdlc2ZGlUTFBwS01CUTM4SmhrYVh0TFdjMzkyUmZ5WXJiOE9kSTBrSStRQ1ZXaWgwWUoxeWxlVwp0Wjl3NXYvMkJoSVRXbmRiR1ZBeEQxSkdIUTVLb21aa2JPaE1XTGRRcjRzSTg5L0lJL1dZNUlHNUtJbDRkRTlICndoUHl4aiszQjFNQzlRVGkxZjJEQWdHUForVVlxK2xoR3ZGRnUzTjQxTmh1SzJnZTlBNnh0ODNDejh1elI0cEMKZ1EyckVrOHlIUmZic3FEQ1U5UUV3bnRVK2lBa285N0F0blloRFFJREFRQUJBb0lCQURmRTIvbXYvWXFDNXVrYwpzbEJoZDJITWhtSk5Nd0d3RStOT2dESjZabXNOdXptUmVYVzFEcGtDMW9ZR0dTb3hJVVdEZm0yaS9KVlFWV1U3Ci93ZzBJSklKUE01NFVqcWxFbnh5dThMT3E0UStxWEhzcjJjZ1ZReTROMTQvcXRuclJaTC9CTlFCOEFJa3d0SWkKTHdHeUtuTThsV3pKT2piU09kQ0dBQnNEdFZGSGpQV2JnNHpmY2dYMy9TNjFvRWVwM2pXenpaZFgwWkdOakpHRApjZGhKRWZqaGJkS2JkblZ3MzhqNjlsZ3k4b0h3ZUNVZ0FNMW4xN3JyeVhFRVJwTVdTSXpzdGUySG02K0x5WnllCmJUNVdUVkI0NW5lYXl6UGp2aHJYMGFFQUlQUDR4bHhDN1Y1bnN4cWlIYllkeGhvMDI1WWU1U0ExWGlNTEhrNUgKSXpubUxLRUNnWUVBOEdpZDhXdmErUUlCUXVFczZtQTRKbnBCR0U5SVRCMTEwMEwza1RCeVNZN0tva1RIczgxUApjbFFQZW44a1ZwUWVEQVVLUnpnTjJqaVNiRUNROWlJTllWS0xWZ0E1djZQeUJLUXZDeFZVTnhLeEFiOW16SmZCCjgzdUJrczFCbWVldUsyMDhudkVHcHBLakpZMk9ZaW42Yk9tVTNlM2ZRVE9xNnkzL3J5S2dvSlVDZ1lFQTdoV2YKd2JDajlZUDJqZFNIZHRvY0NNdHd0QUUyQTgvSVdwS0lVSW43S3IwM3V2M2pQMVpXbjRzYlcrQkRSS2VTbHIxWgpqTFZzbTBZeDVmMUdzeVdyNHo4ZG9MZTIyUmk2TW9PNTNrMVlXRlJBd0ZYRnh2Nk1NSGtadmxOdHc0VVpZQjh3ClVCWndjMnAyNkhXOG5qbncvV2R6bkN3SXBTamRHQjBCNjdYTGlKa0NnWUJJWFVWRm1WQ1ZhWndWbEpBZmtJejIKVUJCdUQ5ZFVTZjNnZEtUdWlDV3VySk9rR28zK09rdXl2MGpWZDVYcGxiWWhxaGE0NzArRUkwazMyb3VIK3lJSgo3SDNTaWtqWHZiS280UDdrR0N4OFUxMENpS21aNWdoVWtSV2txYklZY0p1RnFPRDVldFdrcURrQm9jVjlHT092Cml2UHJoYUdSRDh0ZjlUMmthd2pzclFLQmdRQytrL2lwcHFmWUk2WDhxaDgxZUNud3NFaXJEajBhbC95YzQ2YlMKTVdFb09RYWZYQlBINDJpN2xUSjFQUE1ieGJlRmlsUmdXZWx4OGFLSG8xSXduUHNXa0xNNnIxUmlPM1R3Y3BrWgo1WGZPWE1Mb01zQjZKZEE2RFBZYWI5WHhLRjNEbjdPZ3FCV2pqWmxaUXNXVk1uUkJvOG5iUFRRK1lKTjZkZDNQCnZGb01JUUtCZ1FDdllUU2VNM011aEhoT3NMMzV0cGNjZWVxNDRWbWQvdXZRTkZVaHRNR05MVWJLZVJjdmZvL0QKejMrMEZuTHJrMVBqdTR4Q1M4ZkZ3aHFXRVk4M1R1UGpFeHIrZ0Ztai83VXM0T0pGZ3lyL3hRSXlRaERYd1VIVQpzTkhpZzJUT2RFNFB1Mmt1UXFaRnlVUiswWXFnaFpuTE9WMWRmVG9nQzRkWlFLOEJPdjVpTGc9PQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQo=
extras:
ldap_group: {}
orgchart:
manager_map_file: ../common/manager-map.yaml
groups:
entitlements:
base: ou=Expiration,ou=Entitlements,ou=Groups,dc=kittens,dc=net
create_if_missing: true
backend: dockerized-ldap
internal:
type: dummy
dir: ../../common/internal
pizza_teams:
type: dummy
people:
ldap:
type: ldap
config:
base: ou=People,dc=kittens,dc=net
ldap_binddn: <%= ENV["LDAP_BINDDN"] %>
ldap_bindpw: <%= ENV["LDAP_BINDPW"] %>
ldap_uri: <%= ENV["LDAP_URI"] %>
person_dn_format: uid=%KEY%,ou=People,dc=kittens,dc=net
additional_attributes:
- shellentitlements
people_data_source: ldap

Просмотреть файл

@ -0,0 +1,2 @@
description = Empty entitlement because sub-entitlement is all expired
group = pizza_teams/expired

Просмотреть файл

@ -0,0 +1,4 @@
description = Expired top level entitlement
expiration = 2001-01-01
group = pizza_teams/valid
group = pizza_teams/partial

Просмотреть файл

@ -0,0 +1,3 @@
description = Valid top level entitlement
expiration = 2040-01-01
group = pizza_teams/valid

Просмотреть файл

@ -0,0 +1,3 @@
description = New top level entitlement
expiration = 2040-01-01
group = pizza_teams/valid

Просмотреть файл

@ -0,0 +1,2 @@
description = Valid top level entitlement
group = pizza_teams/*

Просмотреть файл

@ -0,0 +1,5 @@
description = Expired entitlement
expiration = 2001-01-01
username = germanrex
username = khaomanee
username = napoleon

Просмотреть файл

@ -0,0 +1,4 @@
description = Partially expired entitlement
username = ragamuffin; expiration = 2040-01-01
username = blackmanx; expiration = 2001-01-01
username = russianblue

Просмотреть файл

@ -0,0 +1,7 @@
description = Non-expired entitlement
expiration = 2040-01-01
username = nebelung
username = balinese
username = serengeti
username = cheetoh
username = oJosazuLEs

Просмотреть файл

@ -0,0 +1,50 @@
<%-
require "/data/entitlements/lib/entitlements/auditor/gitrepo"
require "/data/entitlements/lib/entitlements/util/gitrepo"
-%>
---
backends:
dockerized-ldap:
ldap_binddn: <%= ENV["LDAP_BINDDN"] %>
ldap_bindpw: <%= ENV["LDAP_BINDPW"] %>
ldap_uri: <%= ENV["LDAP_URI"] %>
person_dn_format: uid=%KEY%,ou=People,dc=kittens,dc=net
type: ldap
configuration_path: ./ldap-config
auditors:
- auditor_class: GitRepo
checkout_directory: <%= ENV["GIT_REPO_CHECKOUT_DIRECTORY"] %>
commit_message: gitrepo-auditor
github_override: git@git-server.fake:/git-server/
git_name: Entitlements Acceptance Test
git_email: entitlements-acceptance-test@noreply.github.com
person_dn_format: uid=%KEY%,ou=People,dc=kittens,dc=net
repo: repos/entitlements-audit
sshkey: |
LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcEFJQkFBS0NBUUVBMzVXUmNrWHRWemd5TFJCN080Mk00b0tVT1A5STBhV0tBVkpSbXhnTmZaMDRBWk8xCmdha0c4RWlvSktldHNaUFhVdzhVZkYyTzk5cjFiQ2dZUHREejVhZ0FmeDRBSS9IOGJBTlN3Z0hpWW9tdVd5VTIKMHZEaitBQndtdlc2ZGlUTFBwS01CUTM4SmhrYVh0TFdjMzkyUmZ5WXJiOE9kSTBrSStRQ1ZXaWgwWUoxeWxlVwp0Wjl3NXYvMkJoSVRXbmRiR1ZBeEQxSkdIUTVLb21aa2JPaE1XTGRRcjRzSTg5L0lJL1dZNUlHNUtJbDRkRTlICndoUHl4aiszQjFNQzlRVGkxZjJEQWdHUForVVlxK2xoR3ZGRnUzTjQxTmh1SzJnZTlBNnh0ODNDejh1elI0cEMKZ1EyckVrOHlIUmZic3FEQ1U5UUV3bnRVK2lBa285N0F0blloRFFJREFRQUJBb0lCQURmRTIvbXYvWXFDNXVrYwpzbEJoZDJITWhtSk5Nd0d3RStOT2dESjZabXNOdXptUmVYVzFEcGtDMW9ZR0dTb3hJVVdEZm0yaS9KVlFWV1U3Ci93ZzBJSklKUE01NFVqcWxFbnh5dThMT3E0UStxWEhzcjJjZ1ZReTROMTQvcXRuclJaTC9CTlFCOEFJa3d0SWkKTHdHeUtuTThsV3pKT2piU09kQ0dBQnNEdFZGSGpQV2JnNHpmY2dYMy9TNjFvRWVwM2pXenpaZFgwWkdOakpHRApjZGhKRWZqaGJkS2JkblZ3MzhqNjlsZ3k4b0h3ZUNVZ0FNMW4xN3JyeVhFRVJwTVdTSXpzdGUySG02K0x5WnllCmJUNVdUVkI0NW5lYXl6UGp2aHJYMGFFQUlQUDR4bHhDN1Y1bnN4cWlIYllkeGhvMDI1WWU1U0ExWGlNTEhrNUgKSXpubUxLRUNnWUVBOEdpZDhXdmErUUlCUXVFczZtQTRKbnBCR0U5SVRCMTEwMEwza1RCeVNZN0tva1RIczgxUApjbFFQZW44a1ZwUWVEQVVLUnpnTjJqaVNiRUNROWlJTllWS0xWZ0E1djZQeUJLUXZDeFZVTnhLeEFiOW16SmZCCjgzdUJrczFCbWVldUsyMDhudkVHcHBLakpZMk9ZaW42Yk9tVTNlM2ZRVE9xNnkzL3J5S2dvSlVDZ1lFQTdoV2YKd2JDajlZUDJqZFNIZHRvY0NNdHd0QUUyQTgvSVdwS0lVSW43S3IwM3V2M2pQMVpXbjRzYlcrQkRSS2VTbHIxWgpqTFZzbTBZeDVmMUdzeVdyNHo4ZG9MZTIyUmk2TW9PNTNrMVlXRlJBd0ZYRnh2Nk1NSGtadmxOdHc0VVpZQjh3ClVCWndjMnAyNkhXOG5qbncvV2R6bkN3SXBTamRHQjBCNjdYTGlKa0NnWUJJWFVWRm1WQ1ZhWndWbEpBZmtJejIKVUJCdUQ5ZFVTZjNnZEtUdWlDV3VySk9rR28zK09rdXl2MGpWZDVYcGxiWWhxaGE0NzArRUkwazMyb3VIK3lJSgo3SDNTaWtqWHZiS280UDdrR0N4OFUxMENpS21aNWdoVWtSV2txYklZY0p1RnFPRDVldFdrcURrQm9jVjlHT092Cml2UHJoYUdSRDh0ZjlUMmthd2pzclFLQmdRQytrL2lwcHFmWUk2WDhxaDgxZUNud3NFaXJEajBhbC95YzQ2YlMKTVdFb09RYWZYQlBINDJpN2xUSjFQUE1ieGJlRmlsUmdXZWx4OGFLSG8xSXduUHNXa0xNNnIxUmlPM1R3Y3BrWgo1WGZPWE1Mb01zQjZKZEE2RFBZYWI5WHhLRjNEbjdPZ3FCV2pqWmxaUXNXVk1uUkJvOG5iUFRRK1lKTjZkZDNQCnZGb01JUUtCZ1FDdllUU2VNM011aEhoT3NMMzV0cGNjZWVxNDRWbWQvdXZRTkZVaHRNR05MVWJLZVJjdmZvL0QKejMrMEZuTHJrMVBqdTR4Q1M4ZkZ3aHFXRVk4M1R1UGpFeHIrZ0Ztai83VXM0T0pGZ3lyL3hRSXlRaERYd1VIVQpzTkhpZzJUT2RFNFB1Mmt1UXFaRnlVUiswWXFnaFpuTE9WMWRmVG9nQzRkWlFLOEJPdjVpTGc9PQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQo=
extras:
ldap_group: {}
orgchart:
manager_map_file: ../common/manager-map.yaml
groups:
entitlements:
base: ou=Expiration,ou=Entitlements,ou=Groups,dc=kittens,dc=net
create_if_missing: true
backend: dockerized-ldap
internal:
type: dummy
dir: ../../common/internal
pizza_teams:
type: dummy
people:
ldap:
type: ldap
config:
base: ou=People,dc=kittens,dc=net
ldap_binddn: <%= ENV["LDAP_BINDDN"] %>
ldap_bindpw: <%= ENV["LDAP_BINDPW"] %>
ldap_uri: <%= ENV["LDAP_URI"] %>
person_dn_format: uid=%KEY%,ou=People,dc=kittens,dc=net
additional_attributes:
- shellentitlements
people_data_source: ldap

Просмотреть файл

@ -0,0 +1,2 @@
description = Empty entitlement because sub-entitlement is all expired
group = pizza_teams/expired

Просмотреть файл

@ -0,0 +1,4 @@
description = Expired top level entitlement
expiration = 2001-01-01
group = pizza_teams/valid
group = pizza_teams/partial

Просмотреть файл

@ -0,0 +1,3 @@
description = Valid top level entitlement
expiration = 2040-01-01
group = pizza_teams/valid

Просмотреть файл

@ -0,0 +1,5 @@
description = Valid top level entitlement
expiration = 2040-01-01
group = pizza_teams/partial
group = pizza_teams/expired
group = pizza_teams/full; expiration = 2001-01-01

Просмотреть файл

@ -0,0 +1,2 @@
description = Valid top level entitlement
group = pizza_teams/*

Просмотреть файл

@ -0,0 +1,5 @@
description = Expired entitlement
expiration = 2001-01-01
username = germanrex
username = khaomanee
username = napoleon

Просмотреть файл

@ -0,0 +1,4 @@
description = Partially expired entitlement
username = ragamuffin; expiration = 2040-01-01
username = blackmanx; expiration = 2001-01-01
username = russianblue

Просмотреть файл

@ -0,0 +1,6 @@
description = Non-expired entitlement
expiration = 2040-01-01
username = nebelung
username = balinese
username = serengeti
username = cheetoh

Просмотреть файл

@ -0,0 +1,3 @@
description = Listing of contractors
username = pixiebob
username = serengeti

Просмотреть файл

@ -0,0 +1,2 @@
description = Listing of pre-hires
username = chartreux

Просмотреть файл

@ -0,0 +1,109 @@
---
nebelung:
status:
- employee
manager: ojosazules
pixiebob:
status:
- contractor
manager: balinese
balinese:
status:
- employee
manager: peterbald
serengeti:
status:
- contractor
manager: balinese
germanrex:
status:
- employee
manager: bengal
khaomanee:
status:
- employee
manager: ojosazules
napoleon:
status:
- employee
manager: napoleon
blackmanx:
status:
- employee
manager: mainecoon
chausie:
status:
- employee
manager: ojosazules
orientallonghair:
status:
- employee
manager: napoleon
korat:
status:
- employee
manager: balinese
oregonrex:
status:
- employee
manager: donskoy
donskoy:
status:
- employee
manager: foldex
russianblue:
status:
- employee
manager: mainecoon
ragamuffin:
status:
- employee
manager: mainecoon
foldex:
status:
- employee
manager: orientallonghair
cheetoh:
status:
- employee
manager: ojosazules
peterbald:
status:
- employee
manager: orientallonghair
mainecoon:
status:
- employee
manager: balinese
cyprus:
status:
- employee
manager: ojosazules
desertlynx:
status:
- employee
manager: bengal
minskin:
status:
- employee
manager: balinese
chartreux:
status:
- pre-hire
manager: bengal
ojosazules:
status:
- employee
manager: donskoy
bobtail:
status:
- employee
manager: bengal
bengal:
status:
- employee
manager: balinese
abyssinian:
status:
- former
manager: balinese

Просмотреть файл

@ -0,0 +1,90 @@
<%-
require "/data/entitlements/lib/entitlements/auditor/gitrepo"
require "/data/entitlements/lib/entitlements/util/gitrepo"
-%>
---
backends:
dockerized-ldap:
ldap_binddn: <%= ENV["LDAP_BINDDN"] %>
ldap_bindpw: <%= ENV["LDAP_BINDPW"] %>
ldap_uri: <%= ENV["LDAP_URI"] %>
person_dn_format: uid=%KEY%,ou=People,dc=kittens,dc=net
type: ldap
configuration_path: ./ldap-config
extras:
ldap_group: {}
orgchart:
manager_map_file: ../common/manager-map.yaml
filters:
contractors:
class: Entitlements::Data::Groups::Calculated::Filters::MemberOfGroup
config:
group: internal/contractors
pre-hires:
class: Entitlements::Data::Groups::Calculated::Filters::MemberOfGroup
config:
group: internal/pre-hires
auditors:
- auditor_class: GitRepo
checkout_directory: <%= ENV["GIT_REPO_CHECKOUT_DIRECTORY"] %>
commit_message: initial-run-commit
github_override: git@git-server.fake:/git-server/
git_name: Entitlements Acceptance Test
git_email: entitlements-acceptance-test@noreply.github.com
person_dn_format: uid=%KEY%,ou=People,dc=kittens,dc=net
repo: repos/entitlements-audit
sshkey: |
LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcEFJQkFBS0NBUUVBMzVXUmNrWHRWemd5TFJCN080Mk00b0tVT1A5STBhV0tBVkpSbXhnTmZaMDRBWk8xCmdha0c4RWlvSktldHNaUFhVdzhVZkYyTzk5cjFiQ2dZUHREejVhZ0FmeDRBSS9IOGJBTlN3Z0hpWW9tdVd5VTIKMHZEaitBQndtdlc2ZGlUTFBwS01CUTM4SmhrYVh0TFdjMzkyUmZ5WXJiOE9kSTBrSStRQ1ZXaWgwWUoxeWxlVwp0Wjl3NXYvMkJoSVRXbmRiR1ZBeEQxSkdIUTVLb21aa2JPaE1XTGRRcjRzSTg5L0lJL1dZNUlHNUtJbDRkRTlICndoUHl4aiszQjFNQzlRVGkxZjJEQWdHUForVVlxK2xoR3ZGRnUzTjQxTmh1SzJnZTlBNnh0ODNDejh1elI0cEMKZ1EyckVrOHlIUmZic3FEQ1U5UUV3bnRVK2lBa285N0F0blloRFFJREFRQUJBb0lCQURmRTIvbXYvWXFDNXVrYwpzbEJoZDJITWhtSk5Nd0d3RStOT2dESjZabXNOdXptUmVYVzFEcGtDMW9ZR0dTb3hJVVdEZm0yaS9KVlFWV1U3Ci93ZzBJSklKUE01NFVqcWxFbnh5dThMT3E0UStxWEhzcjJjZ1ZReTROMTQvcXRuclJaTC9CTlFCOEFJa3d0SWkKTHdHeUtuTThsV3pKT2piU09kQ0dBQnNEdFZGSGpQV2JnNHpmY2dYMy9TNjFvRWVwM2pXenpaZFgwWkdOakpHRApjZGhKRWZqaGJkS2JkblZ3MzhqNjlsZ3k4b0h3ZUNVZ0FNMW4xN3JyeVhFRVJwTVdTSXpzdGUySG02K0x5WnllCmJUNVdUVkI0NW5lYXl6UGp2aHJYMGFFQUlQUDR4bHhDN1Y1bnN4cWlIYllkeGhvMDI1WWU1U0ExWGlNTEhrNUgKSXpubUxLRUNnWUVBOEdpZDhXdmErUUlCUXVFczZtQTRKbnBCR0U5SVRCMTEwMEwza1RCeVNZN0tva1RIczgxUApjbFFQZW44a1ZwUWVEQVVLUnpnTjJqaVNiRUNROWlJTllWS0xWZ0E1djZQeUJLUXZDeFZVTnhLeEFiOW16SmZCCjgzdUJrczFCbWVldUsyMDhudkVHcHBLakpZMk9ZaW42Yk9tVTNlM2ZRVE9xNnkzL3J5S2dvSlVDZ1lFQTdoV2YKd2JDajlZUDJqZFNIZHRvY0NNdHd0QUUyQTgvSVdwS0lVSW43S3IwM3V2M2pQMVpXbjRzYlcrQkRSS2VTbHIxWgpqTFZzbTBZeDVmMUdzeVdyNHo4ZG9MZTIyUmk2TW9PNTNrMVlXRlJBd0ZYRnh2Nk1NSGtadmxOdHc0VVpZQjh3ClVCWndjMnAyNkhXOG5qbncvV2R6bkN3SXBTamRHQjBCNjdYTGlKa0NnWUJJWFVWRm1WQ1ZhWndWbEpBZmtJejIKVUJCdUQ5ZFVTZjNnZEtUdWlDV3VySk9rR28zK09rdXl2MGpWZDVYcGxiWWhxaGE0NzArRUkwazMyb3VIK3lJSgo3SDNTaWtqWHZiS280UDdrR0N4OFUxMENpS21aNWdoVWtSV2txYklZY0p1RnFPRDVldFdrcURrQm9jVjlHT092Cml2UHJoYUdSRDh0ZjlUMmthd2pzclFLQmdRQytrL2lwcHFmWUk2WDhxaDgxZUNud3NFaXJEajBhbC95YzQ2YlMKTVdFb09RYWZYQlBINDJpN2xUSjFQUE1ieGJlRmlsUmdXZWx4OGFLSG8xSXduUHNXa0xNNnIxUmlPM1R3Y3BrWgo1WGZPWE1Mb01zQjZKZEE2RFBZYWI5WHhLRjNEbjdPZ3FCV2pqWmxaUXNXVk1uUkJvOG5iUFRRK1lKTjZkZDNQCnZGb01JUUtCZ1FDdllUU2VNM011aEhoT3NMMzV0cGNjZWVxNDRWbWQvdXZRTkZVaHRNR05MVWJLZVJjdmZvL0QKejMrMEZuTHJrMVBqdTR4Q1M4ZkZ3aHFXRVk4M1R1UGpFeHIrZ0Ztai83VXM0T0pGZ3lyL3hRSXlRaERYd1VIVQpzTkhpZzJUT2RFNFB1Mmt1UXFaRnlVUiswWXFnaFpuTE9WMWRmVG9nQzRkWlFLOEJPdjVpTGc9PQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQo=
groups:
dummy-ou:
type: dummy
dummy-ou-renamed:
type: dummy
dir: dummy-ou-special
entitlements:
backend: dockerized-ldap
base: ou=Entitlements,ou=Groups,dc=kittens,dc=net
entitlements/foo-bar-app:
backend: dockerized-ldap
base: ou=foo-bar-app,ou=Entitlements,ou=Groups,dc=kittens,dc=net
create_if_missing: true
entitlements/groupofnames:
backend: dockerized-ldap
base: ou=GroupOfNames,ou=Entitlements,ou=Groups,dc=kittens,dc=net
plugin:
file: group_of_names.rb
class: GroupOfNames
create_if_missing: true
entitlements/mirror:
backend: dockerized-ldap
base: ou=Mirror,ou=Entitlements,ou=Groups,dc=kittens,dc=net
mirror: entitlements/groupofnames
create_if_missing: true
plugin:
file: posix_group.rb
class: PosixGroup
internal:
type: dummy
dir: ../../common/internal
memberof:
memberof_attribute: shellentitlements
backend: dockerized-ldap
type: member_of
ou:
- entitlements/groupofnames
pizza_teams:
backend: dockerized-ldap
base: ou=Pizza_Teams,ou=Groups,dc=kittens,dc=net
people:
ldap:
type: ldap
config:
base: ou=People,dc=kittens,dc=net
ldap_binddn: <%= ENV["LDAP_BINDDN"] %>
ldap_bindpw: <%= ENV["LDAP_BINDPW"] %>
ldap_uri: <%= ENV["LDAP_URI"] %>
person_dn_format: uid=%KEY%,ou=People,dc=kittens,dc=net
additional_attributes:
- shellentitlements
people_data_source: ldap

Просмотреть файл

@ -0,0 +1 @@
username = maiNecOON

Просмотреть файл

@ -0,0 +1 @@
username = RagaMuffin

Просмотреть файл

@ -0,0 +1 @@
username = ojosazules

Просмотреть файл

@ -0,0 +1,10 @@
---
description: Admin access to primary AWS account
rules:
or:
- entitlements_group: pizza_teams/grumpy-cat
- group: pizza_teams/colonel-meow
expiration: "2050-01-01"
- group: pizza_teams/keyboard-cat
expiration: "2001-01-01"
expiration: "2043-01-01"

Просмотреть файл

@ -0,0 +1,3 @@
description = Group for testing empty membership
username = RAGAMUFFIn
entitlements_group = pizza_teams/empty-but-ok

Просмотреть файл

@ -0,0 +1,4 @@
description = Group for testing empty membership
username = RAGAMUFFIn
username = BlackManx
group != pizza_teams/empty-but-ok

Просмотреть файл

@ -0,0 +1,2 @@
description = Group for testing empty membership
group = pizza_teams/empty-but-ok

Просмотреть файл

@ -0,0 +1,6 @@
description: Group for testing entitlement expiration
expiration: 2043-01-01
rules:
or:
- username: blackmanx
- username: nebelung

Просмотреть файл

@ -0,0 +1,4 @@
description = Group for testing entitlement expiration
username = blackmanx; expiration = 2001-01-01
username = nebelung; expiration = 2001-01-01
expiration = 2001-01-01

Просмотреть файл

@ -0,0 +1,4 @@
description = Group for testing entitlement expiration
username = blackmanx
username = nebelung
expiration = 2001-01-01

Просмотреть файл

@ -0,0 +1,5 @@
description = This is in a sub-ou
username = RUssianblue; expiration = 2050-01-01
username = BlackManx; expiration = 2050-01-01
username = mainecoon; expiration = 2001-01-01
expiration = 2043-01-01

Просмотреть файл

@ -0,0 +1,4 @@
description = This is in a sub-ou
username = russianblue
username = BLACKMANX
metadata_gid_number = 12345

Просмотреть файл

@ -0,0 +1,3 @@
description = This is in a sub-ou
group = dummy-ou/ragamuffin
metadata_gid_number = 23456

Просмотреть файл

@ -0,0 +1,3 @@
username = blackmanx
username = ragamuffin
username = mainecoon

Просмотреть файл

@ -0,0 +1,3 @@
entitlements_group = github/*
entitlements_group != github-org/admin
username = donskoy

Просмотреть файл

@ -0,0 +1,3 @@
description = Fake team on fake GitHub
group = pizza_teams/colonel-meow; expiration = 2050-01-01
username = russianblue; expiration = 2001-01-01

Просмотреть файл

@ -0,0 +1,10 @@
description = Fake team on fake GitHub
metadata_team_id = 4
username = blackmanx
username = russianblue
entitlements_group = dummy-ou-renamed/bacon
username = RagaMuffin
username = cheetoh
username = khaomanee
username = nebelung
group = dummy-ou/tony

Просмотреть файл

@ -0,0 +1,3 @@
description = Fake team on fake GitHub
group = pizza_teams/grumpy-cat; expiration = 2050-01-01
username = foldex; expiration = 2001-01-01

Просмотреть файл

@ -0,0 +1,9 @@
# By virtue of filename this creates pizza_teams/colonel-meow
---
description: Forever known as @russianblue's old team, just kidding
rules:
management: ojosazules
expiration: "2050-01-01"
metadata:
foo: bar

Просмотреть файл

@ -0,0 +1,3 @@
description = This group will some day be empty but that's OK
username = fluffy_kitteninator
metadata_no_members_ok = true

Просмотреть файл

@ -0,0 +1,4 @@
description = This group will some day be empty but that's OK
username = BlackManx
username = fluffy_kitteninator
metadata_no_members_ok = true

Некоторые файлы не были показаны из-за слишком большого количества измененных файлов Показать больше