Privacy Policy
500px is founded on the principle of helping people discover new photos and photographers. We know that you care about how your personal information is used and shared, and we take your privacy very seriously. By visiting the 500px website, registering with 500px or using any 500px services, you are accepting and agree to comply with this policy. The column on the right provides a short explanation of the privacy policy and is not legally binding.
This Privacy Policy covers 500px's treatment of personal information that 500px gathers when you are on the 500px website and when you use 500px services. This policy does not apply to the practices of third parties that 500px does not own or control, or to individuals that 500px does not employ or manage.
Information Collected by 500px
We only collect personal information that is relevant to the purpose of our website. This information allows us to provide you with a customized and efficient experience. We collect the following types of information from our 500px users:
We collect information to make 500px useful for you and to provide a personalized experience.
Information You Provide to Us
- We receive and store any information you enter on our website or provide to us in any other way. You can choose not to provide us with certain information, but then you may not be able to take advantage of many of our special features.
- Registration: In order for you to use 500px services you must complete a registration form. As part of this registration form, we require certain personal information. Our lawful basis for collecting personal information from you is to provide our services and to communicate with you through your consent when you register with us. Our collection of personal information from you is limited to information that we require in order to provide our services to you.
- User Profile: To allow you to express yourself beyond just the information collected during registration, we enable you to provide additional information, such as your first and last names, email address, social media account names, your birthday, a bio, favorite URLs, and instant messaging IDs. In addition, you may choose to include photos of yourself in your profile. As indicated below, in the section titled "Sharing Your Information", you can control how your information is displayed and used.
- You have the right to edit, update, access, or transfer your personal information, or to delete your personal information if you are terminating your registration with 500px.
Automatic Information
- We receive and store certain types of information whenever you interact with us. 500px and its authorized agents automatically receive and record certain "traffic data" on their server logs from your browser and apps including your IP address, 500px cookie information, and the page you requested. 500px uses this traffic data to help diagnose problems with its servers, analyze trends and administer the website. This does not involve collecting any of your personal information.
- In addition to the "traffic data", 500px and its authorized agents may collect information about the device you're using to access 500px, its operating system, unique device identifier, device settings such as language and crash data. Which data is specifically collected depends on the type of device and/or system running on that device. This data is again used to help us diagnose problems with the site and/or mobile apps and analyze trends. This does not involve collecting any of your personal information.
- 500px may collect and use information regarding the geographic location of your devices. If the location data contains your personal information, then 500px will treat this location data in accordance with this Policy.
- 500px may collect and, on any page, display the total counts that page has been viewed. This includes User Profile pages.
- Many companies offer programs that help you to visit websites anonymously. While 500px will not be able to provide you with a personalized experience if we cannot recognize you, we want you to be aware that these programs are available.
We collect your registration and user profile data. Our servers also collect log information used to make the website faster and better. We also collect geographic location data; this allows us to present a more personalized experience.
Communications
E-mail: 500px is very concerned about your privacy and we will never provide your email address to a third party without your explicit permission, as detailed in the "Sharing Your Information" section below. 500px may send out emails with 500px-related news, products, offers, surveys or promotions. You may also receive notification emails from 500px, which inform you of actions (e.g. “new follows”) that have been performed on the site. We send these emails to you based on receiving your consent at registration. If you do not want to receive email from us, please visit the “email Preferences” section of your User Profile and/or follow the “unsubscribe” instructions contained in each email message. However, please note that in all cases you will continue to receive all system emails (e.g. those regarding forgotten user passwords) and legal notices (e.g. updates to our policies) from us unless you terminate your registration.
500px’s messenger service: The 500px messenger service allows you to communicate with other 500px users. 500px may monitor the messenger service as set forth in this Policy, but 500px does not collect any personal information through the messenger service (except as set forth in this Privacy Policy). You can stop using 500px’s messenger service at any time and/or block or report other users attempting to communicate with you through 500px’s messenger service. You are entirely and solely responsible for any information that you disclose or share with other users through 500px’s messenger service or other means. We strongly recommend that you use extreme caution in sharing any personal information with other users through 500px’s messenger service (or otherwise) and 500px is not responsible for any information that you disclose to other users through 500px’s messenger service.
500px monitors the usage of its messenger service to improve its service, but does not read private messages exchanged between users through the 500px’s messenger service unless a user has been reported for inappropriate behavior as outlined in our Terms of Use. If we receive such a report, we will only review the allegedly inappropriate communications that have been reported in order to determine whether they violate our Terms of Use and what actions we will take in response to the conduct (if any), including possibly terminating users. All users have the ability to block parties they do not wish to communicate with via 500px’s messenger service and to stop using 500px’s messenger service at any time.
We will send you emails based on your profile settings. From time to time, we may send emails to all our users. We also won’t read your messages unless you have been reported for behaving inappropriately.
Cookies
Cookies are alphanumeric identifiers that we transfer to your computer's hard drive through your Web browser to enable our systems to recognize your browser and tell us how and when pages in our website are visited and by how many people. 500px cookies do not collect personal information.
500px utilizes third-party services like Google Analytics to help analyze how our site is used. These services, including Google Analytics, also use cookies to collect information about visitors to our site (including IP addresses) in an anonymous form that does not include personal information.
The "help" portion of the toolbar on the majority of browsers will direct you on how to prevent your browser from accepting new cookies, how to command the browser to tell you when you receive a new cookie, or how to fully disable cookies. We recommend that you leave the cookies activated because cookies allow you to use some of 500px's coolest features. Some of our business partners, like our advertisers, may use cookies on our website. We have no access to, or control over, these cookies.
To remember you, our system will give you a cookie. It's safe. Third-party services that help us analyze how our site is used also use cookies to collect information about visitors to our site.
Analytics
500px uses services like Google Analytics and/or Amplitude to help analyze and understand how our site and mobile applications are used, so that we can make 500px products more interesting to you. These tools capture data about how individual users are using our site and mobile applications. This includes event logs, device type and device configuration settings such as language, crash data and other data but never personal information. These third-party services treat the analytics data in accordance with this privacy policy and 500px does not disclose your personal information to any third parties through our use of these services.
We use third-party analytics services that help us better understand usage trends and make decisions based on those trends. These tools don't collect personal information, and all information collected is used in accordance with this policy.
Sharing Your Information
Because 500px enables people to discover and share information with one another, information about the people who use 500px is an integral part of the 500px experience. Rest assured that we will not rent or sell your personal information to anyone and that we will share your personal information only as described below:
- 500px Personnel: 500px personnel and authorized consultants and/or contractors may have access to user information if necessary in the normal course of 500px business.
- Business Transfers: In some cases, we may choose to buy or sell assets. In these types of transactions, user information is typically one of the business assets that is transferred. Moreover, if 500px, or substantially all of its assets, were acquired, user information would be one of the assets that is transferred.
- Protection of 500px and Others: We may release personal information when we believe in good faith that release is necessary to comply with a law; to enforce or apply our Terms of Use and other policies; or to protect the rights, property, or safety of 500px, our employees, our users, or others. This includes exchanging information with other companies and organizations for fraud protection and credit risk reduction.
- User Profile information: Information collected during registration and subsequent visits, such as your full name and location, may be displayed to other 500px users in your User Profile. The User Profile is the area on 500px where we allow you to tell other 500px users about yourself. You may control what personal information is displayed in your User Profile by visiting the Settings section of your User Profile.
- Followers' Activity: Much like other online social networks, 500px allows non-followers to browse your followers’ activity.
- Syndication: 500px allows for the RSS syndication of all of its public content within the 500px website.
- Service Providers: 500px may share user information as well as information from tools such as cookies, log files, device identifiers and location data, with third-parties that help 500px provide services to you (“Service Providers”). Our Service Providers will be given access to your information as is reasonably necessary for 500px to provide our services. 500px requires Services Providers to protect your data in a manner consistent with this Policy and to limit the use of such information to the performance of services for 500px. 500px may also remove parts of data that can identify you and share anonymized data with Service Providers, including combining your information with other information in a way that it is no longer associated with you.
- Data Storage: Your encrypted personal information is stored on servers provided by a third-party cloud-based service provider that protects and stores your data in a manner that is consistent with this Policy.
- With Your Consent: Except as noted above, we will contact you when your personal information is shared with third parties or used for a purpose incompatible with the purpose(s) for which it was originally collected, and you will be able to opt out to prevent the sharing of this information.
We do not sell your information to anyone. However, we will show publicly available information to other users. We may share information so that we can provide our service, and we may share information where required by law. We may also share information with third-parties that help 500px provide services to you
Keeping Information Secure
- Your 500px account information is protected by an encrypted password for your privacy and security. Protect against unauthorized access to your password and to your computer by logging off once you have finished using a shared computer.
- Only employees who need personal information to perform a specific job (for example, a customer service representative) are granted access to it. All of our employees are kept up to date on our privacy and security practices.
Your account is protected by an encrypted password. We keep it secure; you must also keep it safe. Our employees may not access your account unless required to do a specific job.
Ways to Control Display and Use of Your Information
- As stated previously, you can always opt not to disclose information, but then you may be unable to use certain features on our website.
- By visiting your User Profile, you can correct, amend, add or delete personal information on our website.
- If you do not wish to receive email from us or other 500px users, please visit the Settings of your User Profile and/or follow the instructions contained in the unwanted email message.
- However, please note that you will continue to receive all system emails (e.g. those regarding forgotten user passwords) and legal notices (e.g. updates to our policies) from us unless you terminate your registration with 500px.
- As explained earlier, the "help" portion of the toolbar on the majority of browsers will direct you on how to prevent your browser from accepting new cookies, how to command the browser to tell you when you receive a new cookie, or how to fully disable cookies. Please note, however, that if your browser does not accept cookies, you will not be able to take advantage of some of our attractive features.
You can choose not to share information with us, but your experience of the site may be limited. However, until your account is deleted, you may receive all system emails.
Children Under 18 Years of Age
You must be 14 years and older to register to use the 500px website. As a result, 500px does not specifically collect information about children. If we learn that 500px has collected information from a child under the age of 13, we will delete that information as quickly as possible. We recommend that minors between the ages of 14 and 18 ask and receive permission from a legal guardian before using 500px or sending information about themselves or anyone else over the Internet.
Please register only when you reach 18 years of age, or ask for permission for a legal guardian if you are between 14 and 18 years old. You are not allowed to register if you are under 14.
Changes to this Privacy Policy
500px may amend this Privacy Policy from time to time, at its sole discretion. Use of information we collect now is subject to the Privacy Policy in effect at the time such information is used. If we make changes to the Privacy Policy, we will notify you by posting an announcement on the 500px website so you are always aware of what information we collect, how we use it, and under what circumstances if any, it is disclosed.
The Privacy Policy may change.
Conditions of Use
If you decide to visit 500px website, your visit and any possible dispute over privacy is subject to this Privacy Policy and our Terms of Use, including limitations on damages, arbitration of disputes, and application of Ontario law.
Questions
If you have any questions, comments or requests relating to this Privacy Policy, please send an email to<EMAIL_ADDRESS>or you can write to us at:
500px, Inc.
20 Duncan Street, Suite 100
Toronto, Ontario M5H 3G8
Canada
Visiting 500px is subject to our Terms of Use and Privacy Policy.
Effective Date of this Privacy Policy
This Privacy Policy is effective as of May 25, 2018.
Effective as of May 25, 2018.


I gather as many infos as possible about my client needs and desires. This allows to establish a collaborative relationship between the two parts.
Just like a building, the designing phase is as important as the realization. It is much easier to work following a plan rather than jumping towards an unknown goal.
Colors and fonts are carefully selected to create harmony and make navigation enjoyable. Each page has a dynamic layout, necessary for cross-platform browsing.
Before handing over the site to the customer I always make sure that everything is pixel perfect, reputation is everything to me!


Kuklo 2007 f 295 5 423 Karatoprak 2008 1 22 1 26 Yang 2012 4 21 1 21 Hwang 2042 3 56 9 741 Yilmaz 2012 4 35 2 35 Samdani 2013 19 540 441 a7 Total (95% Cl} 969 663
Total events 32 49 Heterogeneity: Chi = 2.11, df= 5 (P = 0.83), F=0% Test for overall effect: Z = 3.80 (P = 0.0001)
40.4% 1.8% 1.9%
15.1% 3.9%
36.8%
100.0%
1.19 (0.07, 20.24]
1.00 (0.06, 17.12) 2012 6.39 (0.10, 1.51] 2012 * 6.49 (0.04, 5.61] 2072 . 0.25 (0.12, 0.55) 2013 7 0.37 (0.22, 0 > + 6.001 O41 1 10 1000 Favours [Pedicle Screw] Favours (Hiybrid Instrumentation |


Food Delights
Home
Selection
Ingredients
Vegetables
Meats
Contact Us
Sign Up
Login
Sign Up
Email:
Password:
Re-enter Password:
Remember me
Submit


Header: #include <modbus.h>
Creates and appends (if there is already a subrequest) a new subrequest to be placed into the WriteFile request message.
uint8_t WriteFileSubRequestBuilder(uint8_t* messageArray, uint8_t currentMessageIndex, uint16_t fileNumber, uint16_t recordNumber, uint8_t recordLength, uint16_t* record);
messageArray
The array to store the subrequests.
currentMessageIndex
The sum of the lengths of the subrequests (0 if its the first/only subrequest).
fileNumber
The ID number of the file to write to.
recordNumber
The index on the file to start writing to.
recordLength
How many pairs of bytes to write.
record
The data to be written.
The new length of the messageArray (to be used for messageLength in WriteFile and currentMessageIndex if you want to use WriteFileSubRequestBuilder to add multiple requests in a single message)


| process_file {xfun} | R Documentation |
Read a text file with the UTF-8 encoding, apply a function to the text, and write back to the original file.
process_file(file, fun = identity, x = read_utf8(file)) sort_file(..., fun = sort)
file |
Path to a text file. |
fun |
A function to process the text. |
x |
The content of the file. |
... |
Arguments to be passed to |
sort_file()
is an application of process_file()
, with the
processing function being sort()
, i.e., it sorts the text lines
in a file and write back the sorted text.
If file
is provided, invisible NULL
(the file is
updated as a side effect), otherwise the processed content (as a character
vector).
f = tempfile() xfun::write_utf8("Hello World", f) xfun::process_file(f, function(x) gsub("World", "woRld", x)) xfun::read_utf8(f) # see if it has been updated file.remove(f)


BLAKE DENTAL CARE
MENU
Home
About
Services
Comments
Kindly give your review on our page;
Add your view
Add
User Rating
4.1 average based on 254 reviews.
5 star
150
4 star
63
3 star
15
2 star
6
1 star
20
Bobby Blake
Stay tuned
connect with us and stay in the loop
Keep loging in to our website to get daily changes
Contact us;0791604221
© Copyright BB 2018 - All rights reserved


{$address.name}
{$address.mobile}
默认
{$address.province}{$address.city}{$address.district}{$address.address}
编辑
新增收货地址


Pizza Size:
Crust Type:
Toppings: ...
How many Pizza(s): ...
Delivered: ...
Your location: ....
....
Phone Number
+250 788 206 956
E-mail Address
semwagacarine@gmail.com


Communicate with Kafka
Every matching event can be sent to an Apache Kafka topic.
SASL mechanism
Create a docker-compose.yml
with the following content
version: "2"
services:
zookeeper:
image: docker.io/bitnami/zookeeper:3.8
ports:
- "2181:2181"
environment:
- ALLOW_ANONYMOUS_LOGIN=yes
kafka:
image: docker.io/bitnami/kafka:3.2
ports:
- "9092:9092"
environment:
- KAFKA_CFG_ZOOKEEPER_CONNECT=zookeeper:2181
- KAFKA_CFG_LISTENER_SECURITY_PROTOCOL_MAP=INTERNAL:PLAINTEXT,CLIENT:SASL_PLAINTEXT
- ALLOW_PLAINTEXT_LISTENER=yes
- KAFKA_CFG_LISTENERS=INTERNAL://:9093,CLIENT://:9092
- KAFKA_CFG_ADVERTISED_LISTENERS=INTERNAL://kafka:9093,CLIENT://kafka:9092
- KAFKA_CFG_INTER_BROKER_LISTENER_NAME=INTERNAL
- KAFKA_CLIENT_USERS=user
- KAFKA_CLIENT_PASSWORDS=password
depends_on:
- zookeeper
Launch the command to create the zookeeper and kafka containers
docker-compose up -d
Create a new exporter on your Otoroshi instance with the following values
PLAINTEXT mechanism
Create a docker-compose.yml
with the following content
version: "2"
services:
zookeeper:
image: docker.io/bitnami/zookeeper:3.8
ports:
- "2181:2181"
environment:
- ALLOW_ANONYMOUS_LOGIN=yes
kafka:
image: docker.io/bitnami/kafka:3.2
ports:
- "9092:9092"
environment:
- KAFKA_CFG_ZOOKEEPER_CONNECT=zookeeper:2181
- KAFKA_CFG_LISTENER_SECURITY_PROTOCOL_MAP=INTERNAL:PLAINTEXT,CLIENT:PLAINTEXT
- ALLOW_PLAINTEXT_LISTENER=yes
- KAFKA_CFG_LISTENERS=INTERNAL://:9093,CLIENT://:9092
- KAFKA_CFG_ADVERTISED_LISTENERS=INTERNAL://kafka:9093,CLIENT://kafka:9092
- KAFKA_CFG_INTER_BROKER_LISTENER_NAME=INTERNAL
depends_on:
- zookeeper
Launch the command to create the zookeeper and kafka containers
docker-compose up -d
Create a new exporter on your Otoroshi instance with the following values
SSL mechanism
wget https://raw.githubusercontent.com/confluentinc/confluent-platform-security-tools/master/kafka-generate-ssl.sh
chmod +x kafka-generate-ssl.sh
Create a docker-compose.yml
with the following content
version: '3.5'
services:
zookeeper:
image: "wurstmeister/zookeeper:latest"
ports:
- "2181:2181"
kafka:
image: wurstmeister/kafka:2.12-2.2.0
depends_on:
- zookeeper
ports:
- "9092:9092"
environment:
KAFKA_ADVERTISED_LISTENERS: 'SSL://kafka:9092'
KAFKA_LISTENERS: 'SSL://<IP_ADDRESS>:9092'
KAFKA_AUTO_CREATE_TOPICS_ENABLE: 'true'
KAFKA_ZOOKEEPER_CONNECT: 'zookeeper:2181'
KAFKA_SSL_KEYSTORE_LOCATION: '/keystore/kafka.keystore.jks'
KAFKA_SSL_KEYSTORE_PASSWORD: 'otoroshi'
KAFKA_SSL_KEY_PASSWORD: 'otoroshi'
KAFKA_SSL_TRUSTSTORE_LOCATION: '/truststore/kafka.truststore.jks'
KAFKA_SSL_TRUSTSTORE_PASSWORD: 'otoroshi'
KAFKA_SSL_ENDPOINT_IDENTIFICATION_ALGORITHM: ''
KAFKA_CFG_SSL_ENDPOINT_IDENTIFICATION_ALGORITHM: ''
KAFKA_SECURITY_INTER_BROKER_PROTOCOL: 'SSL'
volumes:
- ./truststore:/truststore
- ./keystore:/keystore
Launch the command to create the zookeeper and kafka containers
docker-compose up -d
Create a new exporter on your Otoroshi instance with the following values
SASL_SSL mechanism
Generate the TLS certificates for the Kafka broker.
Create a file generate.sh
with the following content and run the command
chmod +x generate.sh && ./generate.sh
# Content of the generate.sh file
version: '3.5'
services:
zookeeper:
image: "bitnami/zookeeper:latest"
ports:
- "2181:2181"
environment:
- ALLOW_ANONYMOUS_LOGIN=yes
kafka:
image: bitnami/kafka:latest
depends_on:
- zookeeper
ports:
- '9092:9092'
environment:
ALLOW_PLAINTEXT_LISTENER: 'yes'
KAFKA_ZOOKEEPER_PROTOCOL: 'PLAINTEXT'
KAFKA_CFG_ZOOKEEPER_CONNECT: 'zookeeper:2181'
KAFKA_CFG_LISTENER_SECURITY_PROTOCOL_MAP: 'INTERNAL:PLAINTEXT,CLIENT:SASL_SSL'
KAFKA_CFG_LISTENERS: 'INTERNAL://:9093,CLIENT://:9092'
KAFKA_INTER_BROKER_LISTENER_NAME: 'INTERNAL'
KAFKA_CFG_ADVERTISED_LISTENERS: 'INTERNAL://kafka:9093,CLIENT://kafka:9092'
KAFKA_CLIENT_USERS: 'user'
KAFKA_CLIENT_PASSWORDS: 'password'
KAFKA_CERTIFICATE_PASSWORD: 'otoroshi'
KAFKA_TLS_TYPE: 'JKS'
KAFKA_OPTS: "-Djava.security.auth.login.config=/opt/kafka/kafka_server_jaas.conf"
volumes:
- ./secrets/kafka_server_jaas.conf:/opt/kafka/kafka_server_jaas.conf
- ./truststore/kafka.truststore.jks:/opt/bitnami/kafka/config/certs/kafka.truststore.jks:ro
- ./keystore/kafka.keystore.jks:/opt/bitnami/kafka/config/certs/kafka.keystore.jks:ro
79966b@PMP00131 ~/Downloads/kafka_ssl_setup-master
79966b@PMP00131 ~/Downloads/kafka_ssl_setup-master cat generate.sh
#!/usr/bin/env bash
set -e
KEYSTORE_FILENAME="kafka.keystore.jks"
VALIDITY_IN_DAYS=3650
DEFAULT_TRUSTSTORE_FILENAME="kafka.truststore.jks"
TRUSTSTORE_WORKING_DIRECTORY="truststore"
KEYSTORE_WORKING_DIRECTORY="keystore"
CA_CERT_FILE="ca-cert"
KEYSTORE_SIGN_REQUEST="cert-file"
KEYSTORE_SIGN_REQUEST_SRL="ca-cert.srl"
KEYSTORE_SIGNED_CERT="cert-signed"
function file_exists_and_exit() {
echo "'$1' cannot exist. Move or delete it before"
echo "re-running this script."
exit 1
}
if [ -e "$KEYSTORE_WORKING_DIRECTORY" ]; then
file_exists_and_exit $KEYSTORE_WORKING_DIRECTORY
fi
if [ -e "$CA_CERT_FILE" ]; then
file_exists_and_exit $CA_CERT_FILE
fi
if [ -e "$KEYSTORE_SIGN_REQUEST" ]; then
file_exists_and_exit $KEYSTORE_SIGN_REQUEST
fi
if [ -e "$KEYSTORE_SIGN_REQUEST_SRL" ]; then
file_exists_and_exit $KEYSTORE_SIGN_REQUEST_SRL
fi
if [ -e "$KEYSTORE_SIGNED_CERT" ]; then
file_exists_and_exit $KEYSTORE_SIGNED_CERT
fi
echo
echo "Welcome to the Kafka SSL keystore and truststore generator script."
echo
echo "First, do you need to generate a trust store and associated private key,"
echo "or do you already have a trust store file and private key?"
echo
echo -n "Do you need to generate a trust store and associated private key? [yn] "
read generate_trust_store
trust_store_file=""
trust_store_private_key_file=""
if [ "$generate_trust_store" == "y" ]; then
if [ -e "$TRUSTSTORE_WORKING_DIRECTORY" ]; then
file_exists_and_exit $TRUSTSTORE_WORKING_DIRECTORY
fi
mkdir $TRUSTSTORE_WORKING_DIRECTORY
echo
echo "OK, we'll generate a trust store and associated private key."
echo
echo "First, the private key."
echo
echo "You will be prompted for:"
echo " - A password for the private key. Remember this."
echo " - Information about you and your company."
echo " - NOTE that the Common Name (CN) is currently not important."
openssl req -new -x509 -keyout $TRUSTSTORE_WORKING_DIRECTORY/ca-key \
-out $TRUSTSTORE_WORKING_DIRECTORY/$CA_CERT_FILE -days $VALIDITY_IN_DAYS
trust_store_private_key_file="$TRUSTSTORE_WORKING_DIRECTORY/ca-key"
echo
echo "Two files were created:"
echo " - $TRUSTSTORE_WORKING_DIRECTORY/ca-key -- the private key used later to"
echo " sign certificates"
echo " - $TRUSTSTORE_WORKING_DIRECTORY/$CA_CERT_FILE -- the certificate that will be"
echo " stored in the trust store in a moment and serve as the certificate"
echo " authority (CA). Once this certificate has been stored in the trust"
echo " store, it will be deleted. It can be retrieved from the trust store via:"
echo " $ keytool -keystore <trust-store-file> -export -alias CARoot -rfc"
echo
echo "Now the trust store will be generated from the certificate."
echo
echo "You will be prompted for:"
echo " - the trust store's password (labeled 'keystore'). Remember this"
echo " - a confirmation that you want to import the certificate"
keytool -keystore $TRUSTSTORE_WORKING_DIRECTORY/$DEFAULT_TRUSTSTORE_FILENAME \
-alias CARoot -import -file $TRUSTSTORE_WORKING_DIRECTORY/$CA_CERT_FILE
trust_store_file="$TRUSTSTORE_WORKING_DIRECTORY/$DEFAULT_TRUSTSTORE_FILENAME"
echo
echo "$TRUSTSTORE_WORKING_DIRECTORY/$DEFAULT_TRUSTSTORE_FILENAME was created."
# don't need the cert because it's in the trust store.
rm $TRUSTSTORE_WORKING_DIRECTORY/$CA_CERT_FILE
else
echo
echo -n "Enter the path of the trust store file. "
read -e trust_store_file
if ! [ -f $trust_store_file ]; then
echo "$trust_store_file isn't a file. Exiting."
exit 1
fi
echo -n "Enter the path of the trust store's private key. "
read -e trust_store_private_key_file
if ! [ -f $trust_store_private_key_file ]; then
echo "$trust_store_private_key_file isn't a file. Exiting."
exit 1
fi
fi
echo
echo "Continuing with:"
echo " - trust store file: $trust_store_file"
echo " - trust store private key: $trust_store_private_key_file"
mkdir $KEYSTORE_WORKING_DIRECTORY
echo
echo "Now, a keystore will be generated. Each broker and logical client needs its own"
echo "keystore. This script will create only one keystore. Run this script multiple"
echo "times for multiple keystores."
echo
echo "You will be prompted for the following:"
echo " - A keystore password. Remember it."
echo " - Personal information, such as your name."
echo " NOTE: currently in Kafka, the Common Name (CN) does not need to be the FQDN of"
echo " this host. However, at some point, this may change. As such, make the CN"
echo " the FQDN. Some operating systems call the CN prompt 'first / last name'"
echo " - A key password, for the key being generated within the keystore. Remember this."
# To learn more about CNs and FQDNs, read:
# https://docs.oracle.com/javase/7/docs/api/javax/net/ssl/X509ExtendedTrustManager.html
keytool -keystore $KEYSTORE_WORKING_DIRECTORY/$KEYSTORE_FILENAME \
-alias localhost -validity $VALIDITY_IN_DAYS -genkey -keyalg RSA
echo
echo "'$KEYSTORE_WORKING_DIRECTORY/$KEYSTORE_FILENAME' now contains a key pair and a"
echo "self-signed certificate. Again, this keystore can only be used for one broker or"
echo "one logical client. Other brokers or clients need to generate their own keystores."
echo
echo "Fetching the certificate from the trust store and storing in $CA_CERT_FILE."
echo
echo "You will be prompted for the trust store's password (labeled 'keystore')"
keytool -keystore $trust_store_file -export -alias CARoot -rfc -file $CA_CERT_FILE
echo
echo "Now a certificate signing request will be made to the keystore."
echo
echo "You will be prompted for the keystore's password."
keytool -keystore $KEYSTORE_WORKING_DIRECTORY/$KEYSTORE_FILENAME -alias localhost \
-certreq -file $KEYSTORE_SIGN_REQUEST
echo
echo "Now the trust store's private key (CA) will sign the keystore's certificate."
echo
echo "You will be prompted for the trust store's private key password."
openssl x509 -req -CA $CA_CERT_FILE -CAkey $trust_store_private_key_file \
-in $KEYSTORE_SIGN_REQUEST -out $KEYSTORE_SIGNED_CERT \
-days $VALIDITY_IN_DAYS -CAcreateserial
# creates $KEYSTORE_SIGN_REQUEST_SRL which is never used or needed.
echo
echo "Now the CA will be imported into the keystore."
echo
echo "You will be prompted for the keystore's password and a confirmation that you want to"
echo "import the certificate."
keytool -keystore $KEYSTORE_WORKING_DIRECTORY/$KEYSTORE_FILENAME -alias CARoot \
-import -file $CA_CERT_FILE
rm $CA_CERT_FILE # delete the trust store cert because it's stored in the trust store.
echo
echo "Now the keystore's signed certificate will be imported back into the keystore."
echo
echo "You will be prompted for the keystore's password."
keytool -keystore $KEYSTORE_WORKING_DIRECTORY/$KEYSTORE_FILENAME -alias localhost -import \
-file $KEYSTORE_SIGNED_CERT
echo
echo "All done!"
echo
echo "Delete intermediate files? They are:"
echo " - '$KEYSTORE_SIGN_REQUEST_SRL': CA serial number"
echo " - '$KEYSTORE_SIGN_REQUEST': the keystore's certificate signing request"
echo " (that was fulfilled)"
echo " - '$KEYSTORE_SIGNED_CERT': the keystore's certificate, signed by the CA, and stored back"
echo " into the keystore"
echo -n "Delete? [yn] "
read delete_intermediate_files
if [ "$delete_intermediate_files" == "y" ]; then
rm $KEYSTORE_SIGN_REQUEST_SRL
rm $KEYSTORE_SIGN_REQUEST
rm $KEYSTORE_SIGNED_CERT
fi
Create, in the same repository, a repository named secrets
with the following configuration.
# Content of ~/tmp/kafka/secrets/kafka_server_jaas.conf
Client {
org.apache.kafka.common.security.plain.PlainLoginModule required
username="user"
password="password";
};
Create a docker-compose.yml
file with the following content.
version: '3.5'
services:
zookeeper:
image: "bitnami/zookeeper:latest"
ports:
- "2181:2181"
environment:
- ALLOW_ANONYMOUS_LOGIN=yes
kafka:
image: bitnami/kafka:latest
depends_on:
- zookeeper
ports:
- '9092:9092'
environment:
ALLOW_PLAINTEXT_LISTENER: 'yes'
KAFKA_ZOOKEEPER_PROTOCOL: 'PLAINTEXT'
KAFKA_CFG_ZOOKEEPER_CONNECT: 'zookeeper:2181'
KAFKA_CFG_LISTENER_SECURITY_PROTOCOL_MAP: 'INTERNAL:PLAINTEXT,CLIENT:SASL_SSL'
KAFKA_CFG_LISTENERS: 'INTERNAL://:9093,CLIENT://:9092'
KAFKA_INTER_BROKER_LISTENER_NAME: 'INTERNAL'
KAFKA_CFG_ADVERTISED_LISTENERS: 'INTERNAL://kafka:9093,CLIENT://kafka:9092'
KAFKA_CLIENT_USERS: 'user'
KAFKA_CLIENT_PASSWORDS: 'password'
KAFKA_CERTIFICATE_PASSWORD: 'otoroshi'
KAFKA_TLS_TYPE: 'JKS'
KAFKA_OPTS: "-Djava.security.auth.login.config=/opt/kafka/kafka_server_jaas.conf"
volumes:
- ./secrets/kafka_server_jaas.conf:/opt/kafka/kafka_server_jaas.conf
- ./truststore/kafka.truststore.jks:/opt/bitnami/kafka/config/certs/kafka.truststore.jks:ro
- ./keystore/kafka.keystore.jks:/opt/bitnami/kafka/config/certs/kafka.keystore.jks:ro
At this point, your repository should be
/tmp/kafka
| generate.sh
| docker-compose.yml
| truststore
| kafka.truststore.jks
| keystore
| kafka.keystore.jks
| secrets
| kafka_server_jaas.conf
Launch the command to create the zookeeper and kafka containers
docker-compose up -d
Create a new exporter on your Otoroshi instance with the following values