├── puppetdb ├── pql │ ├── exported_resources.sh │ ├── nodes_by_environment.sh │ ├── nodes_without_a_fact.sh │ ├── certname_by_fact_value.sh │ ├── fact_lookup.sh │ ├── nodes_by_class.sh │ ├── nodes_not_respoinding.sh │ ├── active_nodes_with_specific_role_assigned.sh │ ├── nodes_with_recursive_events.sh │ ├── files_causing_recursive_events.sh │ ├── reports_per_minute.sh │ └── nested_query_multiple_endpoints.sh ├── get_node_info.sh ├── list_resources.sh ├── db_class_query.sh ├── get_exported_resource.sh ├── db_environment_query.sh ├── list_specific_resources.sh ├── fact_query.sh ├── exported_resources.sh ├── get_authenticated_status.sh ├── get_reports.sh ├── get_facts.sh ├── get_unauthenticated_status.sh ├── get_node_record.sh ├── get_packages_for_node.sh ├── get_exported_host_resources.sh ├── list_nodes_with_class.sh ├── resource-query-ast.sh ├── get_old_nodes.sh └── get_all_events_for_time_period.sh ├── puppetserver ├── status │ ├── get_status.sh │ ├── get_simple_plaintext_status.sh │ ├── get_environments.sh │ ├── get_auth_status.sh │ ├── get_compilation_master_plaintext_status.sh │ ├── get_plaintext_status.sh │ └── get_plaintext_status_debug.sh ├── clear_environment_cache.sh ├── rbac │ ├── set_directoryservice.sh │ ├── get_directoryservice.sh │ ├── get_dsgroups.sh │ ├── create_user.sh │ └── ds.json ├── flush_jruby_pool.sh ├── file_metadatas │ ├── get_plugin_metadatas.sh │ └── get_file_metadata.sh ├── show_known_environments.sh └── clear_jruby_pools.sh ├── orchestrator ├── query_jobs.sh ├── inventory.sh └── deploy_environment.sh ├── rbac ├── get_users.sh ├── ds_read.sh ├── ldapsearch_commands.sh ├── ds_write.sh ├── list_tokens.sh ├── create_user.sh ├── roles_view.sh ├── create_role_cd4pe.sh └── disable_nested_group_search.md ├── classifier ├── get_console_groups.sh ├── get_classes.sh ├── update_classes.sh ├── node_classification.sh ├── get_all_services_status.sh ├── get_node_record.sh ├── get_console_groups_master.sh ├── create_group.sh ├── get_node_group.sh ├── explain-201911.sh ├── get_node_group_id.sh ├── get_node_group_parent_id.sh ├── restore_nc_groups.sh ├── pin_to_group.sh ├── update_group.sh ├── check_last_refresh.sh ├── list_groups.sh ├── search_for_a_class.sh ├── explain.sh ├── external_node_script.rb └── nodes_by_node_group.rb ├── codemanager ├── manual_gitlab_webhook_hit.sh ├── deploy_environment.sh ├── setup_codedeployer_user.sh └── manual_deployment.sh ├── ca ├── delete_cert.sh └── revoke_cert.sh ├── puppet ├── get_ca_cert.sh ├── sign_certificate.sh ├── request_a_catalog.sh └── clean_certificate.sh ├── bolt-server └── helloworld.sh ├── ssl └── ssl_client.sh ├── Readme.markdown └── installer └── download_pe_tarball.sh /puppetdb/pql/exported_resources.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | puppet query 'resources { exported = true }' 4 | -------------------------------------------------------------------------------- /puppetdb/get_node_info.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | curl -X GET http://localhost:8080/pdb/query/v4/nodes/$(hostname -f) 3 | -------------------------------------------------------------------------------- /puppetdb/list_resources.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | curl -X GET http://localhost:8080/pdb/query/v4/resources | python -m json.tool 4 | -------------------------------------------------------------------------------- /puppetdb/pql/nodes_by_environment.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | puppet query 'nodes[certname] { report_environment = "production" }' 4 | -------------------------------------------------------------------------------- /puppetdb/pql/nodes_without_a_fact.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | puppet query 'nodes[certname]{ !certname in facts[certname]{ name = "myfact"} }' 4 | -------------------------------------------------------------------------------- /puppetserver/status/get_status.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | curl -k https://localhost:8140/status/v1/services?level=debug > /tmp/$(hostname).json 4 | -------------------------------------------------------------------------------- /puppetdb/pql/certname_by_fact_value.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | puppet query 'facts[certname] { name = "domain" and value = "puppetdebug.vlan" }' 4 | -------------------------------------------------------------------------------- /puppetdb/pql/fact_lookup.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | puppet query 'facts[value] { name = "domain" and certname = "pe-201735-agent.puppetdebug.vlan" }' 4 | -------------------------------------------------------------------------------- /puppetdb/pql/nodes_by_class.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | puppet query 'resources[certname]{ tag = "puppet_enterprise::profile::master" group by certname}' 4 | -------------------------------------------------------------------------------- /orchestrator/query_jobs.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | curl -k -H "X-Authentication:$(cat ~/.puppetlabs/token)" https://$(hostname -f):8143/orchestrator/v1/jobs 4 | -------------------------------------------------------------------------------- /puppetserver/status/get_simple_plaintext_status.sh: -------------------------------------------------------------------------------- 1 | MASTER='split-master' 2 | curl -k -X GET -H "Accept: pson" https://"${MASTER}":8140/status/v1/simple 3 | -------------------------------------------------------------------------------- /orchestrator/inventory.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | curl -k https://$(hostname -f):8143/orchestrator/v1/inventory -H "X-Authentication:$(cat ~/.puppetlabs/token)" 4 | -------------------------------------------------------------------------------- /puppetdb/pql/nodes_not_respoinding.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | puppet query "nodes[certname]{deactivated is null and report_timestamp < \"$(date +%Y-%m-%dT%H:%M:%S)\" }" 4 | -------------------------------------------------------------------------------- /puppetdb/db_class_query.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | su - pe-postgres -s /bin/bash -c "/opt/puppetlabs/server/bin/psql -d pe-classifier -c \"select * from classes\"" > /tmp/classes.txt 4 | -------------------------------------------------------------------------------- /puppetdb/get_exported_resource.sh: -------------------------------------------------------------------------------- 1 | curl http://localhost:8080/v3/nodes//resources --data-urlencode 'query=["and", ["=", "type", "Nagios_host"], ["=", "exported", true]]' 2 | -------------------------------------------------------------------------------- /puppetdb/db_environment_query.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | su - pe-postgres -s /bin/bash -c "/opt/puppetlabs/server/bin/psql -d pe-classifier -c \"select * from environments\"" > /tmp/environments.txt 4 | -------------------------------------------------------------------------------- /rbac/get_users.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | curl --cert $(puppet config print hostcert) --key $(puppet config print hostprivkey) --cacert $(puppet config print localcacert) https://$(hostname -f):4433/rbac-api/v1/users 4 | -------------------------------------------------------------------------------- /puppetdb/list_specific_resources.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | curl -G -X GET http://$(hostname -f):8080/pdb/query/v4/resources --data-urlencode 'query=["=","type", "File"]' | python -m json.tool > /tmp/file-resources.txt 4 | -------------------------------------------------------------------------------- /rbac/ds_read.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | curl https://$(puppet config print certname):4433/rbac-api/v1/ds --cert $(puppet config print hostcert) --key $(puppet config print hostprivkey) --cacert $(puppet config print cacert) 4 | -------------------------------------------------------------------------------- /puppetserver/status/get_environments.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | curl --cert $(puppet config print hostcert) --key $(puppet config print hostprivkey) --cacert $(puppet config print localcacert) https://$(hostname -f):8140/puppet/v3/environments 3 | -------------------------------------------------------------------------------- /rbac/ldapsearch_commands.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ldapsearch -LLL -x -h pe-381-agent-win2008.puppetdebug.vlan -D "cn=testadmin,cn=Users,dc=puppetdebug,dc=vlan" -W -b "dc=puppetdebug,dc=vlan" "(&(objectClass=*)(sAMAccountName=testadmin))" 4 | -------------------------------------------------------------------------------- /orchestrator/deploy_environment.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | curl -k -H "X-Authentication:$(cat ~/.puppetlabs/token)" https://$(hostname -f):8143/orchestrator/v1/command/deploy -X POST -d '{"environment":"production"}' -H "Content-Type: application/json" 4 | -------------------------------------------------------------------------------- /classifier/get_console_groups.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | curl -k https://$(hostname -f):4433/classifier-api/v1/groups --cert $(puppet config print hostcert) --key $(puppet config print hostprivkey) --cacert $(puppet config print localcacert) | python -m json.tool 3 | -------------------------------------------------------------------------------- /codemanager/manual_gitlab_webhook_hit.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | curl -k -v -X POST -H "Content-Type: application/json" "https://$(hostname -f):8170/code-manager/v1/webhook?type=gitlab&token=$(cat ~/.puppetlabs/token)" -d '{ "ref": "refs/heads/production" }' 4 | -------------------------------------------------------------------------------- /puppetdb/pql/active_nodes_with_specific_role_assigned.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | puppet query "resources[certname,title,environment]{ nodes { deactivated is null and report_timestamp > \"$(date -d "2 days ago" +%Y-%m-%dT%H:%M:%S)\" } and title ~ '^Role::Webserver' }" 3 | -------------------------------------------------------------------------------- /puppetserver/clear_environment_cache.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | curl --cert $(puppet config print hostcert) --key $(puppet config print hostprivkey) --cacert $(puppet config print localcacert) -X DELETE https://$(hostname -f):8140/puppet-admin-api/v1/environment-cache 4 | -------------------------------------------------------------------------------- /puppetserver/status/get_auth_status.sh: -------------------------------------------------------------------------------- 1 | curl -X GET --tlsv1 --cert $(puppet config print hostcert) --key $(puppet config print hostprivkey) --cacert $(puppet config print localcacert) https://$(puppet config print server):4433/status/v1/services | python -m json.tool 2 | -------------------------------------------------------------------------------- /puppetserver/status/get_compilation_master_plaintext_status.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | MASTER='split-master' 4 | ENVIRONMENT='production' 5 | curl -k -X GET -H "Accept: pson" https://"${MASTER}":8140/puppet/v3/status/:name?environment="${ENVIRONMENT}" | python -m json.tool 6 | -------------------------------------------------------------------------------- /classifier/get_classes.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | curl https://$(hostname -f):4433/classifier-api/v1/classes --cert $(puppet config print hostcert) --key $(puppet config print hostprivkey) --cacert $(puppet config print localcacert) -H "Content-Type: application/json" |python -m json.tool 4 | -------------------------------------------------------------------------------- /rbac/ds_write.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | curl -X PUT https://$(puppet config print certname):4433/rbac-api/v1/ds --cert $(puppet config print hostcert) --key $(puppet config print hostprivkey) --cacert $(puppet config print cacert) -d "@/vagrant/ds-stuff/ds.json" -H 'Content-Type: application/json' 4 | -------------------------------------------------------------------------------- /classifier/update_classes.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # This command will update classes on the console node 3 | curl -X POST https://$(hostname -f):4433/classifier-api/v1/update-classes?environment=production --cert $(puppet config print hostcert) --key $(puppet config print hostprivkey) --cacert $(puppet config print localcacert) 4 | -------------------------------------------------------------------------------- /puppetdb/fact_query.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # must be run on localhost to not include certs 3 | curl -s -X GET http://localhost:8080/pdb/query/v4/nodes --data-urlencode 'query=[">",["fact", "fact2"], 2]' 4 | 5 | # 3.8 queries 6 | 7 | curl -G 'http://localhost:8080/v3/nodes' --data-urlencode 'query=[">", ["fact", "fact1"], 0]' 8 | -------------------------------------------------------------------------------- /puppetdb/pql/nodes_with_recursive_events.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Get the number of resource events for each node that is not a managed resource. Typically recursive file or tidy files. Useful for looking for a large resource_events table. 4 | 5 | puppet query 'events[certname, count()] { (!resource_title in resources[title]{}) group by certname }' 6 | -------------------------------------------------------------------------------- /ca/delete_cert.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | MASTER="pe-201732-master.puppetdebug.vlan" 4 | AGENT="pe-201732-agent.puppetdebug.vlan" 5 | 6 | curl -k -X DELETE --cert $(puppet config print hostcert) --key $(puppet config print hostprivkey) --cacert $(puppet config print cacert) "https://${MASTER}:8140/puppet-ca/v1/certificate_status/${AGENT}?environment=production" 7 | -------------------------------------------------------------------------------- /puppetdb/pql/files_causing_recursive_events.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Get the number of resource events generated by a manifest that is not a managed resource. Typically recursive file or tidy files. Useful for looking for a large resource_events table. 4 | 5 | puppet query 'events[file, count()] { (!resource_title in resources[title]{}) group by file}' 6 | -------------------------------------------------------------------------------- /classifier/node_classification.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | curl -X POST --cert $(puppet config print hostcert) --key $(puppet config print hostprivkey) --cacert $(puppet config print cacert) https://$(grep server /etc/puppetlabs/puppet/classifier.yaml |cut -d" " -f 2):4433/classifier-api/v1/classified/nodes/pe-201612-agent.puppetdebug.vlan -H "Content-Type: application/json" 3 | -------------------------------------------------------------------------------- /puppetdb/exported_resources.sh: -------------------------------------------------------------------------------- 1 | # Use the reference form of any resource type you want to query for. 2 | 3 | SET_SERVER=$(puppet config print server) 4 | CONSOLE="${CONSOLE:-$SET_SERVER}" 5 | 6 | curl -G -H "Accept: application/json" \ 7 | 'http://${CONSOLE}:8080/pdb/query/v4/resources' \ 8 | --data-urlencode 'query=["=","exported", true]' | jgrep "type=Host" 9 | -------------------------------------------------------------------------------- /puppetserver/rbac/set_directoryservice.sh: -------------------------------------------------------------------------------- 1 | SET_SERVER=$(puppet config print server) 2 | CONSOLE="${CONSOLE:-$SET_SERVER}" 3 | curl -k -X PUT https://${CONSOLE}:4433/rbac-api/v1/ds \ 4 | --cert $(puppet config print hostcert) \ 5 | --key $(puppet config print hostprivkey) \ 6 | --cacert $(puppet config print localcacert) \ 7 | -H "Content-Type: application/json" -d @ds.json 8 | -------------------------------------------------------------------------------- /puppetserver/rbac/get_directoryservice.sh: -------------------------------------------------------------------------------- 1 | SET_SERVER=$(puppet config print server) 2 | CONSOLE="${CONSOLE:-$SET_SERVER}" 3 | curl -k -X GET https://${CONSOLE}:4433/rbac-api/v1/ds \ 4 | --cert $(puppet config print hostcert) \ 5 | --key $(puppet config print hostprivkey) \ 6 | --cacert $(puppet config print localcacert) \ 7 | -H "Content-Type: application/json" | python -m json.tool 8 | -------------------------------------------------------------------------------- /puppetserver/rbac/get_dsgroups.sh: -------------------------------------------------------------------------------- 1 | SET_SERVER="$(puppet config print server)" 2 | CONSOLE="${CONSOLE:-$SET_SERVER}" 3 | curl -k -X GET https://"${CONSOLE}":4433/rbac-api/v1/groups \ 4 | --cert "$(puppet config print hostcert)" \ 5 | --key "$(puppet config print hostprivkey)" \ 6 | --cacert "$(puppet config print localcacert)" \ 7 | -H "Content-Type: application/json" | python -m json.tool 8 | -------------------------------------------------------------------------------- /classifier/get_all_services_status.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | SET_SERVER=$(puppet config print server) 4 | CONSOLE="${CONSOLE:-$SET_SERVER}" 5 | 6 | curl -X GET \ 7 | --tlsv1 \ 8 | --cert $(puppet config print hostcert) \ 9 | --key $(puppet config print hostprivkey) \ 10 | --cacert $(puppet config print localcacert) \ 11 | https://"${CONSOLE}":4433/status/v1/services | python -m json.tool 12 | -------------------------------------------------------------------------------- /rbac/list_tokens.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # There is currently no API to list existing tokens and their expiration dates. This should be addressed by PE-9890 somewhere down the line 3 | # In the meantime, we can query the DB 4 | 5 | su - pe-postgres -s /bin/bash -c "/opt/puppetlabs/server/bin/psql -d pe-rbac -c \"select subjects.login,tokens.expiration FROM subjects LEFT JOIN tokens ON subjects.id = tokens.user_id\"" 6 | -------------------------------------------------------------------------------- /puppetserver/status/get_plaintext_status.sh: -------------------------------------------------------------------------------- 1 | # puppet_enterprise::profile::console::console_services_plaintext_status_enabled must be set to true 2 | # in console, PE Console group, puppet_enterprise::profile::console class, console_services_plaintext_status_enabled 3 | 4 | SET_SERVER=$(puppet config print server) 5 | CONSOLE="${CONSOLE:-$SET_SERVER}" 6 | 7 | curl -X GET http://${CONSOLE}:8123/status/v1/services 8 | -------------------------------------------------------------------------------- /ca/revoke_cert.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | MASTER="pe-201732-master.puppetdebug.vlan" 4 | AGENT="pe-201732-agent.puppetdebug.vlan" 5 | 6 | curl -k -X PUT -H 'Content-Type: application/json' --cert $(puppet config print hostcert) --key $(puppet config print hostprivkey) --cacert $(puppet config print cacert) "https://${MASTER}:8140/puppet-ca/v1/certificate_status/${AGENT}?environment=production" -d '{"desired_state":"revoked"}' 7 | -------------------------------------------------------------------------------- /puppetdb/get_authenticated_status.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | SET_SERVER=$(puppet config print server) 4 | PUPPETDB="${PUPPETDB:-$SET_SERVER}" 5 | curl -X GET \ 6 | --tlsv1 \ 7 | --cert $(puppet config print hostcert) \ 8 | --key $(puppet config print hostprivkey) \ 9 | --cacert $(puppet config print localcacert) \ 10 | https://"${PUPPETDB}":8081/status/v1/services/puppetdb-status | python -m json.tool 11 | -------------------------------------------------------------------------------- /rbac/create_user.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | curl -X POST -H 'Content-Type: application/json' --cert $(puppet config print hostcert) --key $(puppet config print hostprivkey) --cacert $(puppet config print cacert) https://$(head -n 1 /etc/puppetlabs/puppet/classifier.yaml |grep -oP "(?<=server: ).*"):4433/rbac-api/v1/users -d '{"login":"deploy","email":"","display_name":"Deploy User","role_ids": [2],"password":""}' 4 | -------------------------------------------------------------------------------- /puppetdb/get_reports.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | curl -k -G http://localhost:8080/pdb/query/v4/reports --data-urlencode 'query=["=", "certname", "ud1xe5jynyfg2b0.delivery.puppetlabs.net"]' 4 | 5 | # To pull only specific parts of the reports, use the extract parameter: 6 | 7 | # curl -k -G http://localhost:8080/pdb/query/v4/reports --data-urlencode 'query=["extract", "certname", ["=", "certname", "ud1xe5jynyfg2b0.delivery.puppetlabs.net"]]' 8 | -------------------------------------------------------------------------------- /puppetserver/rbac/create_user.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | PASSWORD="puppetlabs" 4 | EMAIL="deploy@puppetlabs.com" 5 | 6 | curl -X POST -H 'Content-Type: application/json' --cert $(puppet config print hostcert) --key $(puppet config print hostprivkey) --cacert $(puppet config print cacert) https://$(hostname -f):4433/rbac-api/v1/users -d '{"login":"deploy","email":"${EMAIL}","display_name":"Deploy User","role_ids": [2],"password":"${PASSWORD}"}' 7 | -------------------------------------------------------------------------------- /puppetdb/get_facts.sh: -------------------------------------------------------------------------------- 1 | SET_SERVER=$(puppet config print server) 2 | CONSOLE="${CONSOLE:-$SET_SERVER}" 3 | 4 | curl -X GET \ 5 | --tlsv1 \ 6 | --data-urlencode query='["and", ["=", "name", "osfamily"], ["=", "value", "RedHat"]]' \ 7 | --cert $(puppet config print hostcert) \ 8 | --key $(puppet config print hostprivkey) \ 9 | --cacert $(puppet config print localcacert) \ 10 | https://${CONSOLE}:8081/pdb/query/v4/facts 11 | -------------------------------------------------------------------------------- /puppetdb/get_unauthenticated_status.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # NOTE: This must be run FROM the PuppetDB Node as PuppetDB is set, by default, 4 | # to only accept unauthenticated requests from localhost. That can be changed, 5 | # however, by changing this setting: https://docs.puppet.com/puppetdb/4.0/configure.html#host 6 | curl -k -X GET -H "Accept: application/json" http://localhost:8080/status/v1/services/puppetdb-status | python -m json.tool 7 | -------------------------------------------------------------------------------- /puppetdb/pql/reports_per_minute.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | puppet query 'reports[count(), to_string(receive_time, "YY-MM-DD HH24:MI")]{ group by to_string(receive_tme, "YY-MM-DD HH24:MI")}' 4 | 5 | # With JQ to parse into the thundering herd type query: 6 | # puppet query 'reports[count(), to_string(receive_time, "YY-MM-DD HH24:MI")]{ group by to_string(receive_tme, "YY-MM-DD HH24:MI")}' | jq -r -s '.[] | sort_by(.to_string) | .[] | "\(.to_string)\t\(.count)"' 7 | -------------------------------------------------------------------------------- /classifier/get_node_record.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | SET_SERVER=$(puppet config print server) 4 | CONSOLE="${CONSOLE:-$SET_SERVER}" 5 | NODE='yournode.puppetdebug.vlan' 6 | 7 | curl -k -X GET https://${CONSOLE}:4433/classifier-api/v1/nodes/${NODE} \ 8 | --cert $(puppet config print hostcert) \ 9 | --key $(puppet config print hostprivkey) \ 10 | --cacert $(puppet config print localcacert) \ 11 | -H "Content-Type: application/json" | python -m json.tool 12 | -------------------------------------------------------------------------------- /classifier/get_console_groups_master.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # This command will pull the console node from the classifier.yaml file, so it can always be run on the master without worrying about the customer mixing up the target system 3 | curl https://$(grep server /etc/puppetlabs/puppet/classifier.yaml |cut -d" " -f 2):4433/classifier-api/v1/groups --cert $(puppet config print hostcert) --key $(puppet config print hostprivkey) --cacert $(puppet config print localcacert) | python -m json.tool 4 | -------------------------------------------------------------------------------- /puppetserver/status/get_plaintext_status_debug.sh: -------------------------------------------------------------------------------- 1 | # puppet_enterprise::profile::console::console_services_plaintext_status_enabled must be set to true 2 | # in console, PE Console group, puppet_enterprise::profile::console class, console_services_plaintext_status_enabled 3 | 4 | SET_SERVER=$(puppet config print server) 5 | CONSOLE="${CONSOLE:-$SET_SERVER}" 6 | 7 | curl -X GET \ 8 | --data-urlencode 'level=debug' \ 9 | http://${CONSOLE}:8123/status/v1/services | python -m json.tool 10 | -------------------------------------------------------------------------------- /puppetdb/get_node_record.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | SET_SERVER=$(puppet config print server) 4 | PUPPETDB="${PUPPETDB:-$SET_SERVER}" 5 | NODE='mynode.puppetdebug.vlan' 6 | 7 | curl -X GET \ 8 | --tlsv1 \ 9 | --cert $(puppet config print hostcert) \ 10 | --key $(puppet config print hostprivkey) \ 11 | --cacert $(puppet config print localcacert) \ 12 | https://${PUPPETDB}:8081/pdb/query/v4/nodes/${NODE} 13 | # VERSION 3 QUERY BELOW 14 | # https://${PUPPETDB}:8081/v3/nodes/${NODE} 15 | -------------------------------------------------------------------------------- /puppetserver/flush_jruby_pool.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | # This is useful when updating puppet module code under /opt. Since that code is read into the active jruby memory space during pe-puppetserver startup, 3 | # flushing the pool prevents you from having to restart the service (which takes forever) 4 | 5 | curl -i --cert $(puppet config print hostcert) --key $(puppet config print hostprivkey) --cacert $(puppet config print localcacert) -X DELETE https://$(hostname -f):8140/puppet-admin-api/v1/jruby-pool 6 | -------------------------------------------------------------------------------- /puppetdb/get_packages_for_node.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | SET_SERVER=$(puppet config print server) 4 | PUPPETDB="${PUPPETDB:-$SET_SERVER}" 5 | 6 | curl -X GET \ 7 | --tlsv1 \ 8 | --data-urlencode 'query=["and", ["=", "type", "Package"], ["=", "certname", "gary.puppetlabs.vm"]]' \ 9 | --cert $(puppet config print hostcert) \ 10 | --key $(puppet config print hostprivkey) \ 11 | --cacert $(puppet config print localcacert) \ 12 | https://"${PUPPETDB}":8081/pdb/query/v4/resources | python -m json.tool 13 | -------------------------------------------------------------------------------- /puppet/get_ca_cert.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # This script gets the Puppet CA certificate from your Puppet master. 4 | # 5 | # https://puppet.com/docs/puppet/5.3/http_api/http_certificate.html 6 | # 7 | 8 | # Either set the MASTER environmental variable at the command line to use 9 | # a custom server, or let the script automatically try the FQDN of the node 10 | # running the script 11 | SET_SERVER=$(hostname -f) 12 | MASTER="${MASTER:-$SET_SERVER}" 13 | 14 | curl -k "https://${MASTER}:8140/puppet-ca/v1/certificate/ca" 15 | -------------------------------------------------------------------------------- /puppetdb/pql/nested_query_multiple_endpoints.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # All 'colorize' packages in Package Inventory: 4 | # puppet query "package_inventory {package_name = 'colorize'} 5 | 6 | # All 'colorize' packages managed by Puppet: 7 | # puppet query "resources {type = 'Package' and title = 'colorize'}" 8 | 9 | # All 'colorize' packages not managed by Puppet in Package Inventory: 10 | puppet query "package_inventory {package_name = 'colorize' and ! certname in resources[certname]{type = 'Package' and title = 'colorize'} }" 11 | -------------------------------------------------------------------------------- /classifier/create_group.sh: -------------------------------------------------------------------------------- 1 | # Create a group for one specific node and create variables on it. 2 | 3 | curl -k -X POST -H 'Content-Type: application/json' https://$(hostname -f):4433/classifier-api/v1/groups --cert $(puppet config print hostcert) --key $(puppet config print hostprivkey) --cacert $(puppet config print localcacert) -d '{"classes": {}, "name": "server.puppet.com", "parent": "00000000-0000-4000-8000-000000000000", "rule": ["or", ["=", "name", "server.puppet.com" ] ], "variables": {"var1": "setting1", "var2": "setting2", "var3": false } }' 4 | -------------------------------------------------------------------------------- /puppet/sign_certificate.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | SET_SERVER=$(puppet config print ca_name | sed 's/^.*\s//') 4 | CA="${CA:-$SET_SERVER}" 5 | NODE='mynode.puppetdebug.vlan' 6 | 7 | curl -X PUT \ 8 | -H "Content-Type: text/pson" \ 9 | --tlsv1 \ 10 | --cert $(puppet config print hostcert) \ 11 | --key $(puppet config print hostprivkey) \ 12 | --cacert $(puppet config print localcacert) \ 13 | https://${CA}:8140/puppet-ca/v1/certificate_status/${NODE}?environment=production \ 14 | --data '{"desired_state":"signed"}' | python -m json.tool 15 | -------------------------------------------------------------------------------- /classifier/get_node_group.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | SET_SERVER=$(puppet config print server) 4 | CONSOLE="${CONSOLE:-$SET_SERVER}" 5 | NODE_GROUP=$1 6 | RUBY=/opt/puppetlabs/puppet/bin/ruby 7 | 8 | curl -s -X GET https://${CONSOLE}:4433/classifier-api/v1/groups \ 9 | --cert $(puppet config print hostcert) \ 10 | --key $(puppet config print hostprivkey) \ 11 | --cacert $(puppet config print localcacert) \ 12 | -H "Content-Type: application/json" \ 13 | | $RUBY -p -e "gsub(/^(\[.*|.+},)({.+\"name\":\"${NODE_GROUP}\".+?}})(,{|\]).+$/, \"\\\\2\")" \ 14 | | python -m json.tool 15 | -------------------------------------------------------------------------------- /codemanager/deploy_environment.sh: -------------------------------------------------------------------------------- 1 | # Make sure you generate a token with puppet access beforehand 2 | # Show credentials with: `puppet access show` 3 | # puppet access login --service-url https://:4433/rbac-api --lifetime 180d 4 | 5 | SET_SERVER=$(puppet config print server) 6 | CODE_MANAGER="${CODE_MANAGER:-$SET_SERVER}" 7 | 8 | curl -k -X POST -H 'Content-Type: application/json' \ 9 | -H "X-Authentication: `cat ~/.puppetlabs/token`" \ 10 | "https://${CODE_MANAGER}:8170/code-manager/v1/deploys" \ 11 | -d '{"environments": ["production"], "wait": true}' 12 | -------------------------------------------------------------------------------- /puppetserver/file_metadatas/get_plugin_metadatas.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # A query to simulate what plugin sync will call to get the file metadatas for plugin sync. 3 | # Note: You can specify the environment in the command, which defaults to production 4 | 5 | curl --cert $(puppet config print hostcert) --key $(puppet config print hostprivkey) --cacert $(puppet config print localcacert) "https://$(puppet config print server):8140/puppet/v3/file_metadatas/plugins?environment=production&links=follow&recurse=true&source_permissions=ignore&ignore=.svn&ignore=CVS&ignore=.git&ignore=.hg&checksum_type=md5" | python -m json.tool 6 | -------------------------------------------------------------------------------- /rbac/roles_view.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # Show the current RBAC roles that are in the PE console 4 | # https://docs.puppet.com/pe/latest/rbac_roles_v1.html#get-roles 5 | # 6 | [[ -f ~/.puppetlabs/token ]] || { echo 'No token found. Please authenticate with "puppet access login" first.' >&2; exit 1; } 7 | 8 | AUTH_TOKEN="$(<~/.puppetlabs/token)" 9 | OPTIONS="-H X-Authentication:${AUTH_TOKEN}" 10 | SET_SERVER=$(puppet agent --configprint server) 11 | CONSOLE="${CONSOLE:-$SET_SERVER}" 12 | 13 | /opt/puppetlabs/puppet/bin/curl -s -X GET $OPTIONS "https://${CONSOLE}:4433/rbac-api/v1/roles" | python -m json.tool 14 | -------------------------------------------------------------------------------- /classifier/explain-201911.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | HOSTNAME=pe-201911-master.puppetdebug.vlan \ 4 | curl -X POST --cert $(puppet config print hostcert) \ 5 | --key $(puppet config print hostprivkey) \ 6 | --cacert $(puppet config print localcacert) \ 7 | https://$(hostname -f):4433/classifier-api/v1/classified/nodes/$HOSTNAME/explanation \ 8 | --data "$(puppet query "inventory[certname,facts] { certname='$HOSTNAME' }" |tail -n +2 |head -n -1 |sed -e 's/^ //' |sed -e 's/^ "certname":/ "name":/' |sed -e 's/^ "facts"/ "fact"/')" \ 9 | -H "Content-Type: application/json" > \ 10 | /tmp/classification-explain-$HOSTNAME.json 11 | -------------------------------------------------------------------------------- /classifier/get_node_group_id.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | SET_SERVER=$(puppet config print server) 4 | CONSOLE="${CONSOLE:-$SET_SERVER}" 5 | NODE_GROUP=$1 6 | RUBY=/opt/puppetlabs/puppet/bin/ruby 7 | 8 | curl -s -X GET https://${CONSOLE}:4433/classifier-api/v1/groups \ 9 | --cert $(puppet config print hostcert) \ 10 | --key $(puppet config print hostprivkey) \ 11 | --cacert $(puppet config print localcacert) \ 12 | -H "Content-Type: application/json" \ 13 | | $RUBY -p -e "gsub(/^(\[.*|.+},)({.+\"name\":\"${NODE_GROUP}\".+?}})(,{|\]).+$/, \"\\\\2\")" \ 14 | | $RUBY -p -e 'gsub(/^.+"id":"(.+?)".+$/, "\\1")' 15 | 16 | -------------------------------------------------------------------------------- /classifier/get_node_group_parent_id.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | SET_SERVER=$(puppet config print server) 4 | CONSOLE="${CONSOLE:-$SET_SERVER}" 5 | NODE_GROUP=$1 6 | RUBY=/opt/puppetlabs/puppet/bin/ruby 7 | 8 | curl -s -X GET https://${CONSOLE}:4433/classifier-api/v1/groups \ 9 | --cert $(puppet config print hostcert) \ 10 | --key $(puppet config print hostprivkey) \ 11 | --cacert $(puppet config print localcacert) \ 12 | -H "Content-Type: application/json" \ 13 | | $RUBY -p -e "gsub(/^(\[.*|.+},)({.+\"name\":\"${NODE_GROUP}\".+?}})(,{|\]).+$/, \"\\\\2\")" \ 14 | | $RUBY -p -e 'gsub(/^.+"parent":"(.+?)".+$/, "\\1")' 15 | 16 | -------------------------------------------------------------------------------- /puppetserver/file_metadatas/get_file_metadata.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Get the metadata for a specific file. 3 | # This example gets the file metadata for a fact. 4 | # Note: this checks the aio_agent_version.rb fact in the production environment. 5 | # You can sub `plugins/facter` for `modules//` to check the metadata for a file in a module. 6 | 7 | curl --cert $(puppet config print hostcert) --key $(puppet config print hostprivkey) --cacert $(puppet config print localcacert) "https://$(puppet config print server):8140/puppet/v3/file_metadata/plugins/facter/aio_agent_version.rb?environment=production" | python -m json.tool 8 | -------------------------------------------------------------------------------- /puppetserver/show_known_environments.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Get the list of environments that the Puppetserver knows about. 3 | # https://docs.puppetlabs.com/puppet/latest/reference/http_api/http_environments.html 4 | 5 | CERT="$(puppet agent --configprint hostcert)" 6 | CACERT="$(puppet agent --configprint localcacert)" 7 | PRVKEY="$(puppet agent --configprint hostprivkey)" 8 | OPTIONS="--cert ${CERT} --cacert ${CACERT} --key ${PRVKEY}" 9 | SET_SERVER=$(puppet agent --configprint server) 10 | CONSOLE="${CONSOLE:-$SET_SERVER}" 11 | 12 | /opt/puppetlabs/puppet/bin/curl -s -X GET $OPTIONS "https://${CONSOLE}:8140/puppet/v3/environments" | python -m json.tool 13 | 14 | -------------------------------------------------------------------------------- /classifier/restore_nc_groups.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Variables for the console node and the classifier dump file 4 | NC_BACKUP='node_classifier_dump.json' 5 | SET_SERVER=$(puppet config print server) 6 | CONSOLE="${CONSOLE:-$SET_SERVER}" 7 | 8 | # Exit if the node classifier backup file isn't found 9 | [[ -f $NC_BACKUP ]] || { echo "Unable to find NC backup: ${NC_BACKUP}" >&2; exit 1; } 10 | 11 | # Perform the restore 12 | curl -X POST -H 'Content-Type: application/json' \ 13 | --cert "$(puppet config print hostcert)" \ 14 | --key "$(puppet config print hostprivkey)" \ 15 | --cacert "$(puppet config print localcacert)" \ 16 | -d @$NC_BACKUP \ 17 | "https://${CONSOLE}:4433/classifier-api/v1/import-hierarchy" 18 | 19 | -------------------------------------------------------------------------------- /puppetserver/rbac/ds.json: -------------------------------------------------------------------------------- 1 | { 2 | "base_dn": "ou=system", 3 | "connect_timeout": 10, 4 | "display_name": "Sample Directory", 5 | "group_lookup_attr": "cn", 6 | "group_member_attr": "uniqueMember", 7 | "group_name_attr": "description", 8 | "group_object_class": "*", 9 | "group_rdn": "ou=groups", 10 | "help_link": "", 11 | "hostname": "my.ldap.com", 12 | "login": "uid=admin,ou=system", 13 | "password": "secret", 14 | "port": 10389, 15 | "ssl": false, 16 | "start_tls": null, 17 | "search_nested_groups": false, 18 | "type": null, 19 | "user_display_name_attr": "displayName", 20 | "user_email_attr": "mail", 21 | "user_lookup_attr": "cn", 22 | "user_rdn": "ou=users" 23 | } 24 | -------------------------------------------------------------------------------- /classifier/pin_to_group.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Change the group to match the node group needed. This is for PE Master for compile master additions. 4 | curl -k https://$(hostname -f):4433/classifier-api/v1/groups --cert $(puppet config print hostcert) --key $(puppet config print hostprivkey) --cacert $(puppet config print localcacert) | python -m json.tool |grep -C 5 "PE Master" 5 | 6 | # Use the "id" field from the above in the URL to add the rule for the new master 7 | curl -X POST -H 'Content-Type: application/json' --cert $(puppet config print hostcert) --key $(puppet config print hostprivkey) --cacert $(puppet config print localcacert) https://$(hostname -f):4433/classifier-api/v1/groups/9492547d-dbfb-4165-9b1c-f45fd143ed25/pin?nodes=pe-201645-master.puppetdebug.vlan 8 | -------------------------------------------------------------------------------- /puppetdb/get_exported_host_resources.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # This script searches PuppetDB specifically for any Host entries that 3 | # have been marked as 'exported' with Puppet (i.e. someone declared an exported 4 | # host resource like @@host { ... }). I wrote this for our Architect class, but 5 | # you can modify the query to do whatever you like 6 | 7 | SET_SERVER=$(puppet config print server) 8 | PUPPETDB="${PUPPETDB:-$SET_SERVER}" 9 | 10 | curl -X GET \ 11 | --tlsv1 \ 12 | --data-urlencode query='["and", ["=","exported", true], ["=", "type", "Host"]]' \ 13 | --cert $(puppet config print hostcert) \ 14 | --key $(puppet config print hostprivkey) \ 15 | --cacert $(puppet config print localcacert) \ 16 | https://${PUPPETDB}:8081/pdb/query/v4/resources | python -m json.tool 17 | -------------------------------------------------------------------------------- /puppetdb/list_nodes_with_class.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # This shell script makes it easy to see what nodes are applying a class, given 4 | # on the command line. For instance, to see what nodes have profile::base 5 | # 6 | # ./list_nodes_with_class.sh 'Profile::Base' 7 | 8 | SET_SERVER=$(puppet config print server) 9 | PUPPETDB="${PUPPETDB:-$SET_SERVER}" 10 | CLASS_NAME=$1 11 | 12 | curl -X GET \ 13 | --tlsv1 \ 14 | --stderr /dev/null \ 15 | --data-urlencode "query=[\"and\",[\"=\",\"type\",\"Class\"],[\"=\",\"title\",\"${CLASS_NAME}\"]]" \ 16 | --cert $(puppet config print hostcert) \ 17 | --key $(puppet config print hostprivkey) \ 18 | --cacert $(puppet config print localcacert) \ 19 | https://"${PUPPETDB}":8081/pdb/query/v4/resources | python -m json.tool \ 20 | | grep 'certname' 21 | -------------------------------------------------------------------------------- /puppetdb/resource-query-ast.sh: -------------------------------------------------------------------------------- 1 | # Send an AST based query to PDB. This is what CD4PE uses, so it allows one to repro cd4pe PDB interactions 2 | # Expects a file named `query.txt` to exist in the $CWD. The contents of that file is just the AST query itself 3 | # 4 | # for example: 5 | # ["extract", [["function", "count"]], ["=","type","File"]] 6 | # 7 | # Uses ruby to do the url-encode because the curl --url-encode cannot be used at the same time as the -G flag, 8 | # which is needed for this query to work. 9 | 10 | curl -G -X GET --cert $(puppet config print hostcert) --key $(puppet config print hostprivkey) --cacert $(puppet config print localcacert) https://$(hostname -f):8081/pdb/query/v4/resources -d "query=$(cat query.txt | /opt/puppetlabs/puppet/bin/ruby -e 'require "cgi"; while STDIN.gets; puts CGI.escape $_; end')" 11 | -------------------------------------------------------------------------------- /rbac/create_role_cd4pe.sh: -------------------------------------------------------------------------------- 1 | curl -X POST -H 'Content-Type: application/json' --cert $(puppet config print hostcert) --key $(puppet config print hostprivkey) --cacert $(puppet config print localcacert) https://$(hostname -f):4433/rbac-api/v1/roles -d '{"description":"CD4PE user role","display_name":"CD4PE Role","user_ids":[],"group_ids":[],"permissions":[{"object_type":"node_groups","action":"modify_children","instance":"*"},{"object_type":"node_groups","action":"set_environment","instance":"*"},{"object_type":"node_groups","action":"view","instance":"*"},{"object_type":"puppet_agent","action":"run","instance":"*"},{"object_type":"environment","action":"deploy_code","instance":"*"},{"object_type":"nodes","action":"view_data","instance":"*"},{"object_type":"node_groups","action":"edit_config_data","instance":"*"},{"object_type":"orchestrator","action":"view","instance":"*"}]}' 2 | -------------------------------------------------------------------------------- /classifier/update_group.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | curl -X POST -H "Content-type: application/json" \ 3 | > --data \ 4 | > '{ 5 | > "name": "couch_demo_2", 6 | > "classes": {"ntp": {}}, 7 | > "environment": "production", 8 | > "environment_trumps": false, 9 | > "parent": "00000000-0000-4000-8000-000000000000", 10 | > "rule": [ 11 | > "and", 12 | > [ 13 | > "~", 14 | > [ 15 | > "fact", 16 | > "pe_version" 17 | > ], 18 | > ".+" 19 | > ] 20 | > ], 21 | > "variables": {"foo": "bar"} 22 | > }' \ 23 | > --cert $(puppet config print hostcert) \ 24 | > --key $(puppet config print hostprivkey) \ 25 | > --cacert $(puppet config print localcacert) \ 26 | > https://$(puppet config print server):4433/classifier-api/v1/groups/e90dc676-2031-446f-9d4b-21d017392a4d 27 | -------------------------------------------------------------------------------- /classifier/check_last_refresh.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Get the timestamp of the last class update in the Node Classifier. 3 | # This can be run from any Puppet Master or the Puppet Console. 4 | # https://docs.puppetlabs.com/pe/latest/nc_last_class_update.html 5 | 6 | CONFDIR="$(puppet master --configprint confdir)" 7 | 8 | CERT="$(puppet master --confdir "${CONFDIR}" --configprint hostcert)" 9 | CACERT="$(puppet master --confdir "${CONFDIR}" --configprint localcacert)" 10 | PRVKEY="$(puppet master --confdir "${CONFDIR}" --configprint hostprivkey)" 11 | OPTIONS="--cert ${CERT} --cacert ${CACERT} --key ${PRVKEY}" 12 | SET_SERVER=CONSOLE="$(awk '/server: /{print $NF}' "${CONFDIR}/classifier.yaml")" 13 | CONSOLE="${CONSOLE:-$SET_SERVER}" 14 | 15 | /opt/puppetlabs/puppet/bin/curl -s -X GET $OPTIONS "https://${CONSOLE}:4433/classifier-api/v1/last-class-update" | python -m json.tool 16 | 17 | -------------------------------------------------------------------------------- /bolt-server/helloworld.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | cat > test.json << EOF 3 | { 4 | "target": { 5 | "hostname": "$(hostname -f)", 6 | "user": "root", 7 | "password": "puppetlabs", 8 | "host-key-check": false 9 | }, 10 | "task": { 11 | "name": "echo", 12 | "metadata": { 13 | "description": "Echo a message", 14 | "parameters": { 15 | "message": "Default string" 16 | } 17 | }, 18 | "file": { 19 | "filename": "echo.sh", 20 | "file_content": "IyEvdXNyL2Jpbi9lbnYgYmFzaAplY2hvICRQVF9tZXNzYWdlCg==\n" 21 | } 22 | }, 23 | "parameters": { 24 | "message": "Hello world" 25 | } 26 | } 27 | EOF 28 | 29 | curl -X POST -H "Content-Type: application/json" -d @test.json --cacert $(puppet config print localcacert) --cert $(puppet config print hostcert) --key $(puppet config print hostprivkey) https://$(hostname -f):62658/ssh/run_task 30 | -------------------------------------------------------------------------------- /puppetdb/get_old_nodes.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # The -I argument doesn't work in OS X -_- 4 | # Feel free to adjust the days 5 | CUTOFF_DATE=$(date -u +"%Y-%m-%dT%H:%M:%SZ" -d '-1 day') 6 | SET_SERVER=$(puppet config print server) 7 | PUPPETDB="${PUPPETDB:-$SET_SERVER}" 8 | 9 | curl -X GET \ 10 | --tlsv1 \ 11 | --cert $(puppet config print hostcert) \ 12 | --key $(puppet config print hostprivkey) \ 13 | --cacert $(puppet config print localcacert) \ 14 | --data-urlencode "query=[\"<\", \"report_timestamp\", \"${CUTOFF_DATE}\"]" \ 15 | https://${PUPPETDB}:8081/pdb/query/v4/nodes | python -m json.tool 16 | 17 | # If you have jq installed, you can get the certnames by piping to jq with 18 | # the below query: 19 | # https://${PUPPETDB}:8081/pdb/query/v4/nodes | /vagrant/jq '.[].certname' 20 | 21 | # VERSION 3 QUERY ENDPOINT BELOW 22 | # https://${PUPPETDB}:8081/v3/nodes 23 | -------------------------------------------------------------------------------- /classifier/list_groups.sh: -------------------------------------------------------------------------------- 1 | 1. Pull the facts from the target node, for example using ssh: ssh agentnode.puppet.com puppet facts > facts.json. These could also be programmatically pulled from the /pdb/query/v4/facts PDB endpoint using the certname of the target agent as in the query data (https://docs.puppet.com/puppetdb/4.1/api/query/v4/facts.html#pdbqueryv4facts) 2 | 2. If using the output of puppet facts, make the data match the schema for the explanation endpoint by removing the "timeout" and "expiration" json entries in the resulting file and renaming "values" to "fact" 3 | 3. Post this data into the explanation endpoint: 4 | 5 | curl -X POST --cert $(puppet config print hostcert) --key $(puppet config print hostprivkey) --cacert $(puppet config print localcacert) https://$(hostname -f):4433/classifier-api/v1/classified/nodes/vvvbbc6595llm2s.delivery.puppetlabs.net/explanation --data @facts5.json -H "Content-Type: application/json" 6 | -------------------------------------------------------------------------------- /puppet/request_a_catalog.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # This script retrieves a catalog from Puppet's catalog endpoint by generating 4 | # and submitting Facter facts from the current node. 5 | # 6 | # https://docs.puppet.com/puppet/latest/http_api/http_catalog.html 7 | # 8 | 9 | # Either set the MASTER environmental variable at the command line to use 10 | # a custom server, or let the script automatically try the FQDN of the node 11 | # running the script 12 | SET_SERVER=$(hostname -f) 13 | MASTER="${MASTER:-$SET_SERVER}" 14 | 15 | 16 | curl -X POST \ 17 | --cert $(puppet config print hostcert) \ 18 | --key $(puppet config print hostprivkey) \ 19 | --cacert $(puppet config print cacert) \ 20 | https://$MASTER:8140/puppet/v3/catalog/$MASTER?environment=production \ 21 | --data-urlencode 'facts_format=pson' \ 22 | --data-urlencode "facts=$(/opt/puppetlabs/puppet/bin/ruby -rcgi -e "puts CGI.escape('$(puppet facts find --render-as json)')")" 23 | 24 | 25 | -------------------------------------------------------------------------------- /puppetserver/clear_jruby_pools.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Run this on a puppetserver to delete its JRuby pools to clear their cache. 3 | # A response of "HTTP/1.1 204 No Content" means it worked. 4 | # 5 | # https://docs.puppetlabs.com/puppetserver/latest/admin-api/v1/jruby-pool.html 6 | 7 | SET_SERVER=$(hostname -f) 8 | CONSOLE="${CONSOLE:-$SET_SERVER}" 9 | 10 | CONFDIR="$(puppet master --configprint confdir)" 11 | 12 | CERT="$(puppet master --confdir "${CONFDIR}" --configprint hostcert)" 13 | PRIVKEY="$(puppet master --confdir "${CONFDIR}" --configprint hostprivkey)" 14 | CACERT="$(puppet master --confdir "${CONFDIR}" --configprint localcacert)" 15 | 16 | /opt/puppetlabs/puppet/bin/curl -s -i -X DELETE \ 17 | --cert "$CERT" \ 18 | --key "$PRIVKEY" \ 19 | --cacert "$CACERT" \ 20 | "https://${CONSOLE}:8140/puppet-admin-api/v1/jruby-pool" 21 | -------------------------------------------------------------------------------- /classifier/search_for_a_class.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # This script searches the puppetserver API for all known classes that match ^pe_.* 3 | # Adjust the search pattern to tailor this script to your particular search pattern. 4 | 5 | SET_SERVER=$(puppet config print server) 6 | CONSOLE="${CONSOLE:-$SET_SERVER}" 7 | 8 | # Set variables for the curl. 9 | CERT="/etc/puppetlabs/puppet/ssl/certs/$(puppet config print certname).pem" 10 | KEY="/etc/puppetlabs/puppet/ssl/private_keys/$(puppet config print certname).pem" 11 | CACERT="/etc/puppetlabs/puppet/ssl/certs/ca.pem" 12 | 13 | /opt/puppetlabs/puppet/bin/curl -s -X GET \ 14 | --header "Content-Type: application/json" \ 15 | --cert "$CERT" \ 16 | --key "$KEY" \ 17 | --cacert "$CACERT" \ 18 | "https://${CONSOLE}:8140/puppet/v3/resource_types/^pe_.*?environment=production&kind=class" | python -m json.tool | grep \"name\" 19 | 20 | -------------------------------------------------------------------------------- /classifier/explain.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh 2 | 3 | HOSTNAME=machineto.look.up curl -X POST --cert $(puppet config print hostcert) --key $(puppet config print hostprivkey) --cacert $(puppet config print localcacert) https://$(hostname -f):4433/classifier-api/v1/classified/nodes/$HOSTNAME/explanation --data "$(ssh $HOSTNAME puppet facts |egrep -v '(timestamp":|expiration":)' |sed -e 's/"values":/"fact":/' |sed -e 's/^ },$/ }/')" -H "Content-Type: application/json" 4 | 5 | # This one will query for the last facts submitted. Can be run on the AIO master without needing an ssh login to pull the facts 6 | HOSTNAME=machineto.look.up curl -X POST --cert $(puppet config print hostcert) --key $(puppet config print hostprivkey) --cacert $(puppet config print localcacert) https://$(hostname -f):4433/classifier-api/v1/classified/nodes/$(hostname -f)/explanation --data "$(puppet query 'inventory[certname,facts] { certn 7 | ame = $HOSTNAME }' |tail -n +2 |head -n -1 |sed -e 's/^ //' |sed -e 's/^ "certname":/ "name":/' |sed -e 's/^ "facts"/ "fact"/')" -H "Content-Type: application/json" 8 | -------------------------------------------------------------------------------- /ssl/ssl_client.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # Quick way to test out puppet SSL connections that are giving crazy ssl errors, 3 | # adapted from http://www.masterzen.fr/2010/11/14/puppet-ssl-explained/ to not 4 | # need you to type any paths. Ctrl+f to send a request. Thanks to Ben Ford from 5 | # Puppet.com for putting me on to this! 6 | # 7 | # Monitor the output of the command carefully! The slightest error or warning 8 | # can mean that something is screwing up your SSL converstation, eg I had 9 | # 10 | # 2251144968090600:error:140790E5:SSL routines:SSL23_WRITE:ssl handshake 11 | # failure:s23_lib.c:177: 12 | # 13 | # Which turned out to be a load-balancer downgrading or otherwise messing with 14 | # the SSL conversation... (workaround was to bypass/fix will be to upgrade or 15 | # reconfigure) 16 | 17 | PATH=/opt/puppetlabs/puppet/bin:$PATH 18 | openssl s_client -host $(puppet config print server) -port 8140 -cert $(puppet config print certdir)/$(puppet config print certname).pem -key $(puppet config print privatekeydir)/$(puppet config print certname).pem -CAfile $(puppet config print certdir)/ca.pem 19 | -------------------------------------------------------------------------------- /codemanager/setup_codedeployer_user.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | # Install rbac_user dependencies to general modulepath 4 | puppet module install pltraining-rbac --version 0.0.4 --target-dir /etc/puppetlabs/code/modules/ 5 | puppet module install puppetlabs-stdlib --target-dir /etc/puppetlabs/code/modules/ 6 | puppet module install abrader-gms --version 1.0.2 --target-dir /etc/puppetlabs/code/modules/ 7 | 8 | # Assign the declaration to $CODE 9 | # NOTE: The 'Code Deployers' role is NEW to Puppet Enterprise 2016.4.x 10 | # If you're using an older version, you'll need to create the role 11 | # and then assign it to this user. For more help see: 12 | # https://github.com/npwalker/pe_code_manager_webhook/blob/master/manifests/code_manager.pp 13 | read -r -d '' CODE <<-'EOF' 14 | rbac_user { 'codedeployer' : 15 | ensure => 'present', 16 | name => 'codedeployer', 17 | email => 'codedeployer@example.com', 18 | display_name => 'Code Manager Service Account', 19 | password => 'puppetlabs', 20 | roles => [ 'Code Deployers' ], 21 | } 22 | EOF 23 | 24 | # Puppet apply FTW! 25 | puppet apply -e "${CODE}" 26 | -------------------------------------------------------------------------------- /Readme.markdown: -------------------------------------------------------------------------------- 1 | # PE Curl Repo! 2 | 3 | Using Puppet Enterprise APIs is easy, but I constantly forget the curl syntax 4 | because I'm not a damn computer. I noticed prettymuch EVERYONE did the same, 5 | so I made this repo for easy copy/paste-ability. Some things to remember about 6 | these scripts: 7 | 8 | 1. Most have a shebang at the top (`#!/bin/bash`) that are needed for 9 | them to be executable. Some do not. Add/remove/modify as need arises. 10 | 2. Most ARE NOT executable, but will need to be MADE EXECUTABLE to be executed 11 | (I'll leave that as an exercise to the reader, too). 12 | 3. Most need to be run as `root` to access the correct Puppet certs. If you 13 | get an error about unauthenticated RBAC access or authentication, check 14 | to make sure you're running as root. 15 | 4. Most have variables for the server you're hitting as well as a node name 16 | (if applicable). Some early scripts use `$(puppet config print server)` 17 | to target a server. I'm gonna err on the side of setting a server variable 18 | when I see any scripts using the old style. 19 | 20 | Feel free to add more scripts but try to keep them organized (and feel free to 21 | correct me when I mess it up too). 22 | -------------------------------------------------------------------------------- /installer/download_pe_tarball.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # This script will download the requested version of PE from S3. 3 | # If no version is specified, the latest version will be used. It will 4 | # also resume broken downloads to save time and rename the resultant file. 5 | 6 | # INSTALLER CHOICES # 7 | # Either pass these environment variables inline or modify the default 8 | # values (note, it's the value after the ':-' but before the close curly brace } 9 | DOWNLOAD_DIST=${DOWNLOAD_DIST:-el} 10 | DOWNLOAD_RELEASE=${DOWNLOAD_RELEASE:-7} 11 | DOWNLOAD_ARCH=${DOWNLOAD_ARCH:-x86_64} 12 | DOWNLOAD_VERSION=${DOWNLOAD_VERSION:-latest} 13 | 14 | if [[ $DOWNLOAD_VERSION == latest ]]; then 15 | latest_released_version_number="$(curl -s http://versions.puppet.com.s3-website-us-west-2.amazonaws.com/ | tail -n1)" 16 | DOWNLOAD_VERSION=${latest_released_version_number:-latest} 17 | fi 18 | 19 | tarball_name="puppet-enterprise-${DOWNLOAD_VERSION}-${DOWNLOAD_DIST}-${DOWNLOAD_RELEASE}-${DOWNLOAD_ARCH}.tar.gz" 20 | 21 | echo "Downloading PE $DOWNLOAD_VERSION for ${DOWNLOAD_DIST}-${DOWNLOAD_RELEASE}-${DOWNLOAD_ARCH} to: ${tarball_name}" 22 | echo 23 | 24 | curl --progress-bar \ 25 | -L \ 26 | -o "./${tarball_name}" \ 27 | -C - \ 28 | "https://pm.puppetlabs.com/cgi-bin/download.cgi?dist=${DOWNLOAD_DIST}&rel=${DOWNLOAD_RELEASE}&arch=${DOWNLOAD_ARCH}&ver=${DOWNLOAD_VERSION}" 29 | 30 | -------------------------------------------------------------------------------- /puppetdb/get_all_events_for_time_period.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # This script searches PuppetDB's events endpoint for all events between a set 3 | # time period (24 hours before right now and 24 hours after right now). 4 | 5 | SET_SERVER=$(puppet config print server) 6 | PUPPETDB="${PUPPETDB:-$SET_SERVER}" 7 | 8 | # Get appropriately formatted timestamps 9 | # NOTE: this command won't run on BSD `date` because of the -I argument, 10 | # so ensure GNU date is around. 11 | # 12 | # Here's the manpage on the -I argument: 13 | # -I[FMT], --iso-8601[=FMT] 14 | # output date/time in ISO 8601 format. FMT='date' for date only (the 15 | # default), 'hours', 'minutes', 'seconds', or 'ns' for date and time to the 16 | # indicated precision. Example: 2006-08-14T02:34:56-0600 17 | # 18 | TOMORROW=`date -d '+1 day' -Isec` 19 | YESTERDAY=`date -d '-1 day' -Isec` 20 | 21 | # Other individual queries... 22 | #--data-urlencode "query=[\">\", \"run_end_time\", \"${YESTERDAY}\"]" \ 23 | #--data-urlencode "query=[\"<\", \"run_end_time\", \"${TOMORROW}\"]" \ 24 | 25 | curl -X GET \ 26 | --tlsv1 \ 27 | --data-urlencode "query=[\"and\", [\">\", \"run_end_time\", \"${YESTERDAY}\"], [\"<\", \"run_end_time\", \"${TOMORROW}\"]]" \ 28 | --cert $(puppet config print hostcert) \ 29 | --key $(puppet config print hostprivkey) \ 30 | --cacert $(puppet config print localcacert) \ 31 | https://${PUPPETDB}:8081/pdb/query/v4/events | python -m json.tool 32 | -------------------------------------------------------------------------------- /puppet/clean_certificate.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # To emulate a `puppet cert clean ` using the API, we do 2 operations: 4 | # 1. PUT (SAVE) with a desired_state of 'revoked' 5 | # 2. DELETE 6 | # 7 | # https://docs.puppet.com/puppet/4.5/reference/http_api/http_certificate_status.html 8 | # 9 | # To authenticate with a certficate other than pe-internal-dashboard, you must 10 | # add that certificate name to auth.conf's certificate_status rule on the CA. 11 | # 12 | 13 | SET_SERVER=$(puppet config print ca_name | sed 's/^.*\s//') 14 | CA="${CA:-$SET_SERVER}" 15 | NODE='test_node.puppet.vm' 16 | 17 | curl -X PUT \ 18 | -H "Content-Type: text/pson" \ 19 | --data '{"desired_state":"revoked"}' \ 20 | --silent \ 21 | --tlsv1 \ 22 | --cert /etc/puppetlabs/puppet/ssl/certs/pe-internal-dashboard.pem \ 23 | --key /etc/puppetlabs/puppet/ssl/private_keys/pe-internal-dashboard.pem \ 24 | --cacert /etc/puppetlabs/puppet/ssl/certs/ca.pem \ 25 | https://${CA}:8140/puppet-ca/v1/certificate_status/${NODE}?environment=production | python -m json.tool 26 | 27 | curl -X DELETE \ 28 | --tlsv1 \ 29 | --silent \ 30 | --cert /etc/puppetlabs/puppet/ssl/certs/pe-internal-dashboard.pem \ 31 | --key /etc/puppetlabs/puppet/ssl/private_keys/pe-internal-dashboard.pem \ 32 | --cacert /etc/puppetlabs/puppet/ssl/certs/ca.pem \ 33 | https://${CA}:8140/puppet-ca/v1/certificate_status/${NODE}?environment=production | python -m json.tool 34 | 35 | # View cert status. After cleaninig, it should be "not found". 36 | #curl -X GET \ 37 | # --tlsv1 \ 38 | # --cert /etc/puppetlabs/puppet/ssl/certs/pe-internal-dashboard.pem \ 39 | # --key /etc/puppetlabs/puppet/ssl/private_keys/pe-internal-dashboard.pem \ 40 | # --cacert /etc/puppetlabs/puppet/ssl/certs/ca.pem \ 41 | # https://${CA}:8140/puppet-ca/v1/certificate_status/${NODE}?environment=production 42 | 43 | -------------------------------------------------------------------------------- /codemanager/manual_deployment.sh: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | # 3 | # This script can be run to manually trigger Code Manager to deploy code from your control-repo. This sort of 4 | # thing is neccesary when, for example: 5 | # - You've turned on Code Manager but have not yet made an RBAC token. 6 | # - You want to pull down the latest version of a Puppetfile module without pushing to your GMS. 7 | # - Something has broken the post-receive hook on your GMS that would've triggered Code Manager. 8 | # - Syntax errors in your Puppetfile prevent you from retrieving those fixes to that Puppetfile. 9 | # - Puppetserver has crashed due to file-sync issues between code and code-staging. 10 | 11 | [[ $EUID -eq 0 ]] || { echo "${0##*/} must be run as root or with sudo" >&2; exit 1; } 12 | 13 | echo "==> Fixing permissions on the code-staging directory" 14 | chown -R pe-puppet:pe-puppet /etc/puppetlabs/code-staging 15 | 16 | echo "==> Running r10k manually as pe-puppet to fetch new code" 17 | sudo -u pe-puppet bash -c '/opt/puppetlabs/puppet/bin/r10k deploy environment -c /opt/puppetlabs/server/data/code-manager/r10k.yaml -p -v debug' 18 | 19 | deploy_result=$? 20 | [[ $deploy_result -eq 0 ]] || { echo -e "\nR10k failed to deploy your code. Check the scroll-back for errors.\n" >&2; exit 1; } 21 | 22 | echo "==> Delete environments in the code-dir so file-sync can do its thing" 23 | rm -rf /etc/puppetlabs/code/* 24 | 25 | echo "==> Fixing permissions on the code directory" 26 | chown pe-puppet:pe-puppet /etc/puppetlabs/code 27 | 28 | echo "==> Starting pe-puppetserver" 29 | /opt/puppetlabs/puppet/bin/puppet resource service pe-puppetserver ensure=running 30 | 31 | # Set variables for the curl. 32 | CERT="$(puppet agent --configprint hostcert)" 33 | KEY="$(puppet agent --configprint hostprivkey)" 34 | CACERT="$(puppet agent --configprint localcacert)" 35 | SERVER="$(puppet agent --configprint server)" 36 | 37 | echo "==> Hitting the file-sync commit endpoint at https://${SERVER}:8140/file-sync/v1/commit" 38 | /opt/puppetlabs/puppet/bin/curl -v -s --request POST \ 39 | --header "Content-Type: application/json" \ 40 | --data '{"commit-all": true}' \ 41 | --cert "${CERT}" \ 42 | --key "${KEY}" \ 43 | --cacert "${CACERT}" \ 44 | "https://${SERVER}:8140/file-sync/v1/commit" && echo 45 | 46 | -------------------------------------------------------------------------------- /rbac/disable_nested_group_search.md: -------------------------------------------------------------------------------- 1 | # Console RBAC: Disable Nested Group Search 2 | 3 | When the PE console is configured to use LDAP, it can sometimes be slow to process a login. This is because a nested-group search is being performed, which is inefficient. 4 | 5 | 6 | 7 | To drastically speed up LDAP login time, follow these steps: 8 | 9 | 1. Grab the current LDAP config from the console: 10 | 11 | ``` 12 | # Create an RBAC token to access the API (requires pe-client-tools, or run this from the master) 13 | puppet-access login 14 | 15 | # Dump the RBAC directory settings to JSON 16 | curl -k -X GET https://:4433/rbac-api/v1/ds -H "X-Authentication:$(puppet-access show)" > ds.json 17 | ``` 18 | 19 | 1. Edit the resultant `ds.json` file changing only the `search_nested_groups` field to `false`. 20 | 1. POST the new config to the console 21 | 22 | ``` 23 | curl -k https://:4433/rbac-api/v1/ds -H "X-Authentication:$(puppet-access show)" -H "Content-Type: application/json" -X PUT --data @ds.json 24 | ``` 25 | 26 | ## Windows 27 | 28 | Same thing but for Windows people. This requires at least PowerShell 5. 29 | 30 | ```powershell 31 | #this is so you can trust your puppet master cert... you can trust it right?.. mine still owes me about $20 32 | add-type @" 33 | using System.Net; 34 | using System.Security.Cryptography.X509Certificates; 35 | public class TrustAllCertsPolicy : ICertificatePolicy { 36 | public bool CheckValidationResult( 37 | ServicePoint srvPoint, X509Certificate certificate, 38 | WebRequest request, int certificateProblem) { 39 | return true; 40 | } 41 | } 42 | "@ 43 | [System.Net.ServicePointManager]::CertificatePolicy = New-Object TrustAllCertsPolicy 44 | 45 | $token = "dear god this is a long variable... like i get we want it unique and it is .. boy it is, but the powerball number is a lot smaller .. just saying" 46 | 47 | $servername= "" 48 | 49 | 50 | #i bet there is a better way to do this too.. but hey 51 | $headers = New-Object "System.Collections.Generic.Dictionary[[String],[String]]" 52 | $headers.Add("X-Authentication", "$token") 53 | $headers.Add("Content-Type", "application/json") 54 | 55 | 56 | #get what we have 57 | $results2 = Invoke-RestMethod -Uri "https://${servername}:4433/rbac-api/v1/ds" -Headers $headers -Method Get 58 | #lets be sure we are bool 59 | $results2.search_nested_groups = [bool]$false 60 | #ps loves objects... really loves them.. so lets be sure we are talking the right way 61 | $body = $results2 | ConvertTo-Json 62 | 63 | Invoke-RestMethod -Uri "https://${servername}:4433/rbac-api/v1/ds" -Headers $headers -Method Put -Body $body 64 | 65 | ``` 66 | -------------------------------------------------------------------------------- /classifier/external_node_script.rb: -------------------------------------------------------------------------------- 1 | #!/opt/puppetlabs/puppet/bin/ruby 2 | # 3 | # The /nodes endpoint is now authenticated, and has an actual terminus. 4 | # As such, the external_nodes script was deprecated. It was, however, 5 | # useful for debugging, and for teaching how the node classifier works. 6 | # 7 | # This is a simple reimplementation that calls the actual endpoint for 8 | # manual debugging. It will just show you the json representation of the 9 | # node's classification. It should be called just like the old script. 10 | # 11 | # external_node.rb 12 | # 13 | # Minor improvements from https://gist.github.com/nicklewis/7a750cfa8985171ea18a 14 | 15 | require 'json' 16 | require 'net/http' 17 | require 'openssl' 18 | require 'socket' 19 | require 'yaml' 20 | require 'puppet' 21 | require 'optparse' 22 | 23 | class SimpleClassifier 24 | class HttpClient 25 | def initialize(server) 26 | cert = Puppet.settings[:hostcert] #`puppet master --configprint hostcert`.strip 27 | cacert = Puppet.settings[:localcacert] #`puppet master --configprint localcacert`.strip 28 | prvkey = Puppet.settings[:hostprivkey] #`puppet master --configprint hostprivkey`.strip 29 | 30 | @prefix = server.path 31 | @client = Net::HTTP.new(server.host, server.port).tap do |client| 32 | client.use_ssl = true 33 | client.cert = OpenSSL::X509::Certificate.new(File.read(cert)) 34 | client.key = OpenSSL::PKey::RSA.new(File.read(prvkey)) 35 | client.ca_file = cacert 36 | end 37 | end 38 | 39 | def get(uri) 40 | headers = {'Accept' => 'application/json'} 41 | result = @client.get(File.join(@prefix, uri), headers) 42 | 43 | if result.is_a? Net::HTTPSuccess 44 | JSON.parse(result.body) 45 | else 46 | raise "ERROR in request GET #{uri}: #{result.code} #{result.body}" 47 | end 48 | end 49 | 50 | def post(uri, body) 51 | headers = {'Accept' => 'application/json', 'Content-Type' => 'application/json'} 52 | result = @client.post(File.join(@prefix, uri), body, headers) 53 | 54 | if result.is_a? Net::HTTPSuccess 55 | JSON.parse(result.body) 56 | else 57 | raise "ERROR in request POST #{uri}: #{result.code} #{result.body}" 58 | end 59 | end 60 | end 61 | 62 | def initialize 63 | confdir = Puppet.settings[:confdir] # `puppet master --configprint confdir`.strip 64 | 65 | puppetdb = File.readlines(File.join(confdir, 'puppetdb.conf')).grep(/=/).map do|line| 66 | line.split('=').map(&:strip) 67 | end 68 | puppetdb = Hash[puppetdb] 69 | @puppetdb = HttpClient.new(URI.parse(puppetdb['server_urls'].split(',').first)) 70 | 71 | classifier = YAML.load_file(File.join(confdir, 'classifier.yaml')) 72 | classifier = classifier[0] if classifier.is_a? Array 73 | @classifier = HttpClient.new(URI.parse("https://#{classifier['server']}:#{classifier['port']}#{classifier['prefix']}")) 74 | end 75 | 76 | def facts(node) 77 | facts = @puppetdb.get("/pdb/query/v4/nodes/#{node}/facts") 78 | facts.inject { |h,fact| h.merge!(fact['name'] => fact['value']) } 79 | end 80 | 81 | def classify(node) 82 | facts = facts(node) 83 | trusted = facts.delete('trusted') 84 | body = {'fact' => facts, 85 | 'trusted' => trusted}.to_json 86 | 87 | @classifier.post("/v1/classified/nodes/#{node}", body) 88 | end 89 | end 90 | 91 | ############ Now start execution ############ 92 | 93 | output = :yaml 94 | optparse = OptionParser.new { |opts| 95 | opts.banner = "Usage : external_node.rb [--output yaml|json] 96 | 97 | " 98 | 99 | opts.on("-o FORMAT", "--output FORMAT", "Choose the output format (yaml or json).") do |arg| 100 | output = arg.downcase.to_sym 101 | end 102 | 103 | opts.separator('') 104 | 105 | opts.on("-h", "--help", "Displays this help") do 106 | puts opts 107 | exit 108 | end 109 | } 110 | optparse.parse! 111 | 112 | if ARGV.size != 1 113 | puts "Please call this script with the name of a node." 114 | puts " example usage: external_node.rb " 115 | exit 1 116 | end 117 | 118 | Puppet.initialize_settings(['--confdir', '/etc/puppetlabs/puppet']) 119 | 120 | begin 121 | data = SimpleClassifier.new.classify(ARGV[0]) 122 | 123 | # Don't force an environment if none is set. 124 | data.delete('environment') if data['environment'] == 'agent-specified' 125 | 126 | case output 127 | when :json 128 | puts JSON.pretty_generate(data) 129 | when :yaml 130 | puts data.to_yaml 131 | else 132 | puts "Unknown render format: #{output}" 133 | end 134 | rescue Exception => e 135 | puts "Failed to retrieve classification for #{ARGV[0]}!" 136 | raise e 137 | end 138 | 139 | -------------------------------------------------------------------------------- /classifier/nodes_by_node_group.rb: -------------------------------------------------------------------------------- 1 | #!/opt/puppetlabs/puppet/bin/ruby 2 | 3 | require 'json' 4 | require 'optparse' 5 | 6 | def debug(str) 7 | puts "DEBUG: #{str}" if $options[:debug] 8 | end 9 | 10 | # curl data from a specified url 11 | def curl_data(command) 12 | debug "Running command '#{command}'" 13 | data = `#{command}` 14 | retcode = $?.exitstatus 15 | if(retcode != 0) then 16 | if(retcode == 7) then 17 | puts "ERROR: Unable to reach #{command.match(/(http.*)/)}" 18 | else 19 | puts "ERROR: Failed to curl endpoint, retcode=#{retcode}" 20 | end 21 | exit retcode 22 | end 23 | return data 24 | end 25 | 26 | # List out node groups 27 | def list_groups 28 | $groups.sort_by! { |g| g['name'] } 29 | $groups.each do |g| 30 | # puts "#{g['environment_trumps'] ? '(env group) ' : ''}#{g['name']}" 31 | puts g['name'] 32 | end 33 | return nil 34 | end 35 | 36 | # Create a hash mapping group id to name 37 | def build_id_to_name() 38 | ret = {} 39 | $groups.each do |g| 40 | ret[g['name'].downcase] = g['id'] 41 | end 42 | return ret 43 | end 44 | 45 | # Return a list of rules 46 | def get_rules(arr, group_id,first=true) 47 | $groups.each do |group| 48 | if(group['id'] == group_id) then 49 | if(group['rule'].to_s != '') then 50 | debug "Translating rule '#{group['rule'].to_s}' for group '#{group['name']}'" 51 | 52 | data = curl_data("curl -s -X POST --cert $(puppet config print hostcert) --key $(puppet config print hostprivkey) --cacert $(puppet config print localcacert) https://#{$options[:console]}:4433/classifier-api/v1/rules/translate -H 'Content-Type: application/json' --data '#{group['rule'].to_s}'") 53 | parsed_rules = JSON.parse(data) 54 | 55 | debug "Adding rules translated rules '#{parsed_rules['query'].to_s}'" 56 | arr << parsed_rules['query'].to_s 57 | elsif(first) then 58 | debug "Initial group has no rules, so nothing matches" 59 | arr << '["=","certname","No Matches"]' 60 | return nil 61 | end 62 | if(group['id'] != group['parent']) then 63 | get_rules(arr, group['parent'], false) 64 | end 65 | end 66 | end 67 | return nil 68 | end 69 | 70 | def build_query_string(arr) 71 | if(arr.length == 0) then 72 | debug "No rules found for '#{$group_to_find}'" 73 | debug $groups 74 | elsif(arr.length == 1) 75 | query_string = "#{arr[0]}" 76 | elsif(arr.length == 2) 77 | query_string = "[\"and\",#{arr.join ","}]" 78 | else 79 | query_string = "[\"and\",#{arr.pop},#{arr.pop}]" 80 | while(arr.length > 0) do 81 | query_string = "[\"and\",#{query_string},#{arr.pop}]" 82 | end 83 | end 84 | 85 | # If the query string is empty, then we don't want to match anything. 86 | # if(query_string.nil?) then 87 | # query_string = '["=","certname","No Matches"]' 88 | # end 89 | 90 | query_string.gsub! '"name"', '"certname"' 91 | debug "Final query string = '#{query_string}'" 92 | return query_string 93 | end 94 | 95 | # main 96 | 97 | $options = {} 98 | $options[:console] = `hostname -f`.chomp 99 | $options[:pdb] = $options[:console] 100 | OptionParser.new do |opts| 101 | opts.banner = "Usage: nodes_by_node_group.rb [flags] or nodes_by_node_group.rb --list" 102 | opts.on("-d","--debug","Enable debug output") do |d| 103 | $options[:debug] = d 104 | end 105 | opts.on("-l","--list","List available groups") do |l| 106 | $options[:list] = l 107 | end 108 | opts.on("-p","--puppetdb ","Fully qualified hostname of the PuppetDB node (Required on split installs)") do |p| 109 | $options[:pdb] = p 110 | end 111 | opts.on("-c","--console ","Fully qualified hostname of the Console node (Required on split installs)") do |c| 112 | $options[:console] = c 113 | end 114 | end.parse! 115 | 116 | data = curl_data("curl -s --cert $(puppet config print hostcert) --key $(puppet config print hostprivkey) --cacert $(puppet config print localcacert) https://#{$options[:console]}:4433/classifier-api/v1/groups") 117 | $groups = JSON.parse(data) 118 | 119 | if($options[:list]) then 120 | list_groups 121 | exit 0 122 | end 123 | 124 | $group_to_find ||= ARGV.join " " 125 | $group_to_find = $group_to_find.downcase 126 | if($group_to_find == '') then 127 | puts "No group specified!" 128 | exit -1 129 | end 130 | 131 | id_hash = build_id_to_name 132 | if !(id_hash.has_key?($group_to_find)) then 133 | puts "ERROR: No group named '#{$group_to_find}' present on #{$options[:console]}." 134 | exit -1 135 | end 136 | 137 | get_rules(arr = [], id_hash[$group_to_find]) 138 | query_string = build_query_string(arr) 139 | 140 | data = curl_data("curl -s --cert $(puppet config print hostcert) --key $(puppet config print hostprivkey) --cacert $(puppet config print localcacert) -G https://#{$options[:pdb]}:8081/pdb/query/v4/nodes --data-urlencode 'query=#{query_string}'") 141 | nodes = JSON.parse(data) 142 | 143 | title = "Nodes for the class '#{$group_to_find}'" 144 | puts title 145 | puts "=" * title.length 146 | if(nodes.count != 0) then 147 | nodes.each do |node| 148 | puts node['certname'] 149 | end 150 | end 151 | puts "Total nodes: #{nodes.count}" 152 | --------------------------------------------------------------------------------