Điều kiện tiên quyết
Cần có các ngọc để triển khai máy chủ:
- google-protobuf (sử dụng phiên bản 3.2.X trong hướng dẫn này)
- grpc (sử dụng 1.2.X trong hướng dẫn này)
Tải định nghĩa dịch vụ xuống và tạo cấu trúc thư mục như sau:
[base_dir]
├── certificates
├── lib
├── protos
└── booking_service.proto
└── server.rb
Tạo thư viện Ruby từ phần mô tả giao diện:
$ cd [base_dir]
$ grpc_tools_ruby_protoc -I protos --ruby_out=lib --grpc_out=lib protos/booking_service.proto
Triển khai máy chủ
Triển khai bộ xương:
#!/usr/bin/ruby2.0
# Copyright 2017, Google Inc.
# All rights reserved.
#
# Redistribution and use in source and binary forms, with or without
# modification, are permitted provided that the following conditions are
# met:
#
# * Redistributions of source code must retain the above copyright
# notice, this list of conditions and the following disclaimer.
# * Redistributions in binary form must reproduce the above
# copyright notice, this list of conditions and the following disclaimer
# in the documentation and/or other materials provided with the
# distribution.
# * Neither the name of Google Inc. nor the names of its
# contributors may be used to endorse or promote products derived from
# this software without specific prior written permission.
#
# THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
# "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
# LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
# OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
# SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
# OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
# Sample gRPC server that implements the BookingService and enforces mutual
# authentication.
#
# Usage: $ path/to/server.rb
this_dir = File.expand_path(File.dirname(__FILE__))
lib_dir = File.join(this_dir, 'lib')
$LOAD_PATH.unshift(lib_dir) unless $LOAD_PATH.include?(lib_dir)
require 'grpc'
require 'grpc/health/checker'
require 'grpc/health/v1/health_services_pb'
require 'openssl'
require 'optparse'
require 'booking_service_services_pb.rb'
# Peer certificate validation that checks for a specific CN in the subject
# name. Add additional valid CNs, e.g. for a test client, to the array.
ACCEPTED_CNS = ["mapsbooking.businesslink-3.net"]
def check_peer_cert(grpc_call)
valid_cert = false
certificate = OpenSSL::X509::Certificate.new grpc_call.peer_cert
certificate.subject().to_a().each do |name_entry|
if (name_entry[0] == "CN") && ACCEPTED_CNS.include?(name_entry[1])
valid_cert = true
end
end
unless valid_cert
fail GRPC::BadStatus.new(GRPC::Core::StatusCodes::UNAUTHENTICATED,
"Client cert has invalid CN")
end
end
# BookingServer is a simple server that implements the BookingService.
class BookingServer < Ext::Maps::Booking::Partner::V0::BookingService::Service
PartnerApi = Ext::Maps::Booking::Partner::V0
def initialize(peer_cert_validator)
@peer_cert_validator = peer_cert_validator
end
def create_lease(lease_req, grpc_call)
@peer_cert_validator.call(grpc_call)
lease = lease_req.lease.dup
# Perform availability check etc.
#
# For error conditions (example):
# fail GRPC::BadStatus.new(GRPC::Core::StatusCodes::RESOURCE_EXHAUSTED,
# "Slot unavailable")
#
# Happy path: populate the response
# [...]
# Assign a lease ID
# lease.lease_id = ...
PartnerApi::CreateLeaseResponse.new(lease: lease)
end
def create_booking(booking_req, grpc_call)
@peer_cert_validator.call(grpc_call)
booking = PartnerApi::Booking.new
# Populate booking
# [...]
# Assign a booking ID
# booking.booking_id = ...
PartnerApi::CreateBookingResponse.new(booking: booking)
end
def update_booking(booking_req, grpc_call)
@peer_cert_validator.call(grpc_call)
booking = PartnerApi::Booking.new
# * Look up the booking with ID booking_req.booking.booking_id
# * Update according to the request and return the updated booking.
PartnerApi::UpdateBookingResponse.new(booking: booking)
end
end
# Loads the certificates for the test server.
def load_server_certs
this_dir = File.expand_path(File.dirname(__FILE__))
cert_dir = File.join(this_dir, 'certificates')
# In order:
# * PEM file with trusted root certificates for client auth
# * Server private key
# * PEM file with server certificate chain
files = ['trusted_client_roots.pem', 'server.key', 'server.pem']
files.map { |f| File.open(File.join(cert_dir, f)).read }
end
# Creates ServerCredentials from certificates.
def server_credentials
certs = load_server_certs
GRPC::Core::ServerCredentials.new(
certs[0], [{private_key: certs[1], cert_chain: certs[2]}], true)
end
def main
# Parse command line arguments
disable_tls = false
OptionParser.new do |opts|
opts.on('--disable_tls',
'true to disable TLS. NOT FOR PRODUCTION USE!') do |v|
disable_tls = v
end
end.parse!
s = GRPC::RpcServer.new
# Listen on port 50051 on all interfaces. Update for production use.
s.add_http2_port('[::]:50051',
disable_tls ? :this_port_is_insecure : server_credentials)
cert_validator = disable_tls ? ->(grpc_call) {} : method(:check_peer_cert)
s.handle(BookingServer.new cert_validator)
health_checker = Grpc::Health::Checker.new
health_checker.add_status(
"ext.maps.booking.partner.v0.BookingService",
Grpc::Health::V1::HealthCheckResponse::ServingStatus::SERVING)
s.handle(health_checker)
s.run_till_terminated
end
if __FILE__ == $0
main()
end
Kiểm thử máy chủ mà không dùng TLS (Bảo mật tầng truyền tải)
Trong thử nghiệm ban đầu, bạn có thể tắt TLS:
$ cd [base_dir]
$ ruby server.rb --disable_tls
Nội dung này không phù hợp để sử dụng cho mục đích sản xuất!
Định cấu hình chứng chỉ sản phẩm
Để bật TLS trên máy chủ, bạn cần có những tệp sau:
certificates/server.pem
chuỗi chứng chỉ cho máy chủ ở định dạng PEMcertificates/server.key
khoá riêng tư cho chuỗi chứng chỉ máy chủcertificates/trusted_client_roots.pem
các chứng chỉ gốc đáng tin cậy khi xác thực ứng dụng
Tập hợp các chứng chỉ gốc của ứng dụng đáng tin cậy sẽ được dùng khi xác thực ứng dụng. Bạn có thể chọn lấy tập hợp gốc đáng tin cậy này từ một tổ chức phát hành như Mozilla hoặc cài đặt tập hợp gốc hiện được Cơ quan quản lý Internet của Google G2 đề xuất. Trong trường hợp thứ hai, đôi khi bạn có thể phải cập nhật chứng chỉ gốc theo cách thủ công.
Cấu trúc thư mục cuối cùng
[base_dir]
├── certificates
├── server.pem
├── server.key
└── trusted_client_roots.pem
├── lib
├── booking_service_pb.rb
└── booking_service_services_pb.rb
├── protos
└── booking_service.proto
└── server.rb